home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 October / EnigmA AMIGA RUN 22 (1997)(G.R. Edizioni)(IT)[!][issue 1997-10 & 11][EAR-CD VI].iso / progs / devel / pcq12d_1 / docs / pascal.doc < prev    next >
Text File  |  1992-08-22  |  163KB  |  4,010 lines

  1. ===================================================================
  2.  
  3.                       PCQ Pascal version 1.2
  4.                  A Pascal compiler for the Amiga
  5.                          by Patrick Quaid
  6.  
  7.  
  8. ===================================================================
  9.  
  10. PCQ Pascal is a simple Pascal compiler for the Amiga personal
  11. computer.  It is freely distributable, which means that I retain
  12. the copyright to the compiler, the runtime library, the source of
  13. the compiler and runtime library, as well as this documentation.
  14. This documentation refers to the registered version of PCQ Pascal.
  15. To summarize the compiler's features:
  16.  
  17. The bad:
  18.  
  19.     o  The compiler doesn't support sets.
  20.     o  It isn't compatible with Turbo Pascal, although it's getting
  21.            closer.
  22.     o  Some things are slightly different from Standard Pascal.
  23.     o  The compiler gets knocked for a loop by most errors.
  24.  
  25. The good:
  26.  
  27.     o  It works.
  28.     o  It supports include files.
  29.     o  It allows for separate compilation, although you have to
  30.            do the checking (this isn't Modula-2, after all).
  31.     o  It supports records, enumerated types, pointers, arrays,
  32.            and C strings.
  33.     o  Type casts as found in Modula-2 is supported.  In other
  34.            words, something like "Byte('d')" is legal.
  35.     o  Several features from Turbo and Quick Pascal, such as Exit
  36.            procedures, operators such as Shl and Shr, and typed
  37.            constants, are supported.
  38.     o  You can have as many const, var, type, procedure and
  39.            function blocks as you want, in any order.
  40.  
  41.  
  42.  
  43.  
  44.  
  45. ===================================================================
  46.  
  47.                         Table of Contents
  48.  
  49. ===================================================================
  50.  
  51.  
  52. This manual is designed to be read with a file reader or text
  53. editor, so this table of contents is based on line numbers rather
  54. than page numbers.  See the last section about getting a
  55. page-oriented version.
  56.  
  57.  
  58.         Section                                   Line Number
  59.      -----------------------------------------------------------
  60.  
  61.         Installing PCQ .............................  163
  62.             What have I got here? ..................  167
  63.             How do I make a work disk? .............  198
  64.         Compiling a program ........................  367
  65.         Incompatibilities ..........................  513
  66.  
  67.         PCQ Programs ...............................  559
  68.         Reserved Words .............................  574
  69.         Pascal Program Structure ...................  604
  70.  
  71.         Type Declarations ..........................  677
  72.             Numeric Types ..........................  744
  73.             Other Ordinal Types ....................  780
  74.             Pointer Types ..........................  806
  75.             File Types .............................  836
  76.             Type Compatibility .....................  859
  77.  
  78.         Constant Declarations ......................  888
  79.             Typed Constants ........................  927
  80.             Standard Constants ..................... 1014
  81.  
  82.         Variable Declarations ...................... 1062
  83.             Standard Variables ..................... 1108
  84.  
  85.         Procedure & Function Declarations .......... 1161
  86.             Parameter Passing ...................... 1194
  87.             Unnamed Parameters ..................... 1240
  88.             Forward Procedures & Functions ......... 1299
  89.             External Routines ...................... 1325
  90.             Standard Procedures .................... 1348
  91.             Standard Functions ..................... 1499
  92.  
  93.         Label Declarations ......................... 1678
  94.  
  95.         Expressions ................................ 1702
  96.             Evaluation Order & Short Circuits ...... 1874
  97.             Constant Expressions ................... 1929
  98.             Variable References .................... 1939
  99.  
  100.         Statements ................................. 1977
  101.             If Statements .......................... 1997
  102.             While Statements ....................... 2038
  103.             Repeat Statements ...................... 2054
  104.             For Statements ......................... 2073
  105.             Case Statements ........................ 2117
  106.             With Statements ........................ 2150
  107.             Compound Statements .................... 2186
  108.             Assignment Statements .................. 2202
  109.             Procedure Calls ........................ 2215
  110.             Return Statements ...,.................. 2245
  111.             Goto Statements ........................ 2265
  112.  
  113.         Input/Output ............................... 2297
  114.             Pascal IO .............................. 2302
  115.             Text and Typed Files ................... 2340
  116.             Opening Files .......................... 2390
  117.             Writing to Files ....................... 2484
  118.             Reading from Files ..................... 2552
  119.             File Buffers ........................... 2637
  120.             IO Checking ............................ 2701
  121.             Standard IO ............................ 2728
  122.  
  123.         Strings .................................... 2803
  124.             Allocating String Space ................ 2839
  125.             Using Escape Characters ................ 2886
  126.             StringLib .............................. 2925
  127.  
  128.         Memory Management .......................... 2939
  129.             HeapError .............................. 2975
  130.  
  131.         Exit Procedures ............................ 3009
  132.             Runtime Errors ......................... 3053
  133.  
  134.         Compiler Directives ........................ 3126
  135.  
  136.         Type Casts ................................. 3283
  137.  
  138.         Small Initialization Code .................. 3327
  139.  
  140.         Execution Profiling ........................ 3391
  141.  
  142.         External Files ............................. 3450
  143.  
  144.         Calling Conventions ........................ 3523
  145.  
  146.         Notes to Assembly Programmers .............. 3555
  147.  
  148.         Errors ..................................... 3586
  149.  
  150.         Sources .................................... 3616
  151.  
  152.         Improvements on the Burner ................. 3703
  153.  
  154.         Update History ............................. 3731
  155.  
  156.         Other Notes, Copyright & My Address ........ 3970
  157.  
  158.  
  159.  
  160.  
  161. ===================================================================
  162.  
  163.                           Installing PCQ
  164.  
  165. ===================================================================
  166.  
  167.  What have I got here?
  168. -----------------------
  169.  
  170. The registered version of PCQ Pascal contains the following files:
  171.  
  172.         Pascal          The compiler itself
  173.         Peep            The peephole optimizer
  174.         PCQ             The make utility
  175.         Pascal.DOC      This documentation file
  176.         Readme.PCQ      A short description of PCQ
  177.         PCQ.DOC         Documentation for the make utility
  178.         PCQ.lib.DOC     A description of the PCQ.lib routines
  179.         PCQ.lib         The runtime library
  180.         Include.LZH     The include file library, compressed with
  181.                         the LHArc program.
  182.         Examples.LZH    Several example programs, also compressed
  183.                         with LHArc.
  184.         IDList.LZH      A directory for the include files
  185.         Runtime.LZH     The Pascal and assembly source code of
  186.                         PCQ.lib.
  187.  
  188.         A68k            Charlie Gibbs' assembler
  189.         A68k.doc        The documentation for A68k
  190.         A68k2do.txt     Improvements planned for A68k
  191.         History.log     Version-by-version changes of A68k
  192.  
  193.         Blink           The Software Distillery linker
  194.         Blink.doc       The documentation for Blink
  195.  
  196.  
  197.  
  198.  How do I make a work disk?
  199. ----------------------------
  200.  
  201. Glad you asked.  The answer is that I don't know.  There are
  202. jillions of different system configurations out there, so I can't
  203. tell you exactly how to set your system up.  But I can give you
  204. some general guidelines.
  205.  
  206. First of all, somewhere in your command path you are going to need
  207. the compiler, assembler, linker, and a text editor.  Normally
  208. these would go in the C:  directory, but if you use the AmigaDOS
  209. PATH command, they can go in any of the path directories.
  210.  
  211. If you don't have a text editor, I heartily recommend CygnusEd
  212. Professional from ASDG.  TxEd is supposed to be about as good, but
  213. I've never used it.  Programmers on a budget can use MEMACS from
  214. the Extras disk, ED from the Workbench disk, or a variety of
  215. freely distributable editors like DME.  ED isn't a great choice,
  216. MEMACS is fair, and from what I hear DME is really good.  Take
  217. your pick.
  218.  
  219. The other file you'll definitely need is the runtime library,
  220. which can go anywhere.  I keep mine in my work directory, but
  221. others like to keep it in their LIBS:  directory.  It's up to you,
  222. but don't forget where you put it.
  223.  
  224. These files are all absolutely necessary for even the simplest
  225. programs.  If you want to use any Amiga routines, or use special
  226. routines from PCQ.lib, you will also need to install the include
  227. file library.  This is where it gets a bit hairy, because the set
  228. of include files is just under 800 disk blocks (a little less than
  229. 400k).  That's half a floppy disk right there.  The size of these
  230. files is going to make it awfully hard to use the complete system
  231. on single drive systems.  If you want to install the Include files
  232. you'll also need to find a copy of LHArc (or one of the compatible
  233. archivers).  LHArc is available on virtually all bulletin boards,
  234. so you shouldn't have much of a problem finding a copy (if you
  235. have not yet done so, do yourself a favor and buy a modem.  It's
  236. the best investment you'll make).
  237.  
  238. So how do we organize all this stuff?  It depends on your system,
  239. of course, but here's a few examples.  If you want to install the
  240. program on a hard drive, you could try the following.  First, copy
  241. Pascal, A68k, and Blink to your C:  directory (also copy a text
  242. editor if one is not already there).  Then create a work
  243. directory.  Copy PCQ.lib to this new directory.  Now make a
  244. subdirectory of your work directory called something like
  245. "Include".  It's actually not necessary that it's a subdirectory,
  246. but it will help you keep your disk structure straight.  Then use
  247. the AmigaDOS ASSIGN command to make an assignment of Include:  to
  248. your new include directory.  Now you want to uncompress the
  249. include file library into your new include directory, with a
  250. command like:
  251.  
  252.         LHArc -x -r x DistributionDisk:Include Include:
  253.  
  254. Use the actual path of the include archive, or course.  Every time
  255. you use the compiler, you should be sure to properly ASSIGN the
  256. Include:  directory - you'll probably want to put that assignment
  257. in the startup-sequence or an initialization script.
  258.  
  259.  
  260. If you have one disk drive, I recommend the following disk
  261. structure.  The problem here is that I don't have a one-drive
  262. system on which to test this, so you may have to adjust it
  263. somewhat.
  264.  
  265.     Root:
  266.         PCQ.lib
  267.         C (dir)
  268.             A68k                             Assign
  269.             Avail                            Blink
  270.             CD                               Copy
  271.             Date                             Delete
  272.             Echo                             Ed
  273.             Else                             EndCLI
  274.             EndIf                            EndSkip
  275.             Execute                          Failat
  276.             If                               Info
  277.             Join                             Lab
  278.             List                             LoadWB
  279.             Makedir                          NewShell
  280.             Pascal                           Path
  281.             Prompt                           Protect
  282.             Quit                             Relabel
  283.             Rename                           Resident
  284.             Run                              SetPatch
  285.             Stack                            Type
  286.         Libs (dir)
  287.             diskfont.library                 icon.library
  288.             mathtrans.library                version.library
  289.         Devs (dir)
  290.             ramdrive.device                  system-configuration
  291.         S (dir)
  292.             Startup-Sequence                 Make
  293.         L (dir)
  294.             Disk-Validator                   Newcon-Handler
  295.             Port-Handler                     Ram-Handler
  296.             Shell-Seg                        
  297.         Include (dir)
  298.             All the include files...
  299.         Trashcan (dir)
  300.  
  301.  
  302.  
  303. To make this sort of disk, first make a copy of a standard
  304. Workbench disk.  Then prune away everything, and I mean
  305. everything, that you don't absolutely need.  You'll note for
  306. example that the list above doesn't even have the serial.device
  307. and the parallel.device, so you can't use your modem or printer.
  308. These sorts of sacrifices will have to be made.  Next, copy
  309. Pascal, A68k and Blink to the :c  directory, then copy Make to the
  310. :s  directory and PCQ.lib to the new disk's root.  Make a new
  311. directory called Include, then CD to it.  Uncompress the Include
  312. file directory by using the following command:
  313.  
  314.     LHArc -x -r x Distribution:Include WorkDisk:Include/
  315.  
  316. Use the actual path for LHArc and the archive itself.  You might
  317. have to run Install on the disk to make it bootable, but you'll
  318. have yourself a barely usable work disk for Pascal.  You will have
  319. virtually no free space, so you'll have to edit and compile files
  320. in RAM:, copying them to a separate disk as often as possible.  It
  321. will be a hard life.  If you are only writing very simple,
  322. standard Pascal programs, which use none of the Amiga's special
  323. features, you can leave out the include directory (thus freeing up
  324. nearly 400k), but you won't be able to create very interesting
  325. programs.  Single drive users probably have several tricks up
  326. their sleeves to get around disk space problems, so if you know of
  327. a better plan, by all means use it.
  328.  
  329. If you have two disks, I would recommend a setup similar to the
  330. single drive system.  Move the include directory to the second
  331. disk, however, and flesh out the system files on the boot disk (so
  332. you can use your printer, especially).  Use the ~400k of free
  333. space on your second drive as your work area.  This is the sort of
  334. setup I used when I originally developed PCQ.
  335.  
  336. If you have lots of RAM (say, a megabyte or more), you might want
  337. to copy some of this stuff into RAM:  or RAD:  to free up work
  338. space.  For example, if you have one megabyte of RAM you might be
  339. able to copy the entire Include directory to the RAM:  disk and
  340. still have enough memory to compile medium sized programs.
  341.  
  342. The one optional part of the system is the peephole optimizer,
  343. Peep.  This program takes the assembly output of the compiler and
  344. makes it somewhat more efficient and slightly smaller.  If you are
  345. compiling on floppy disks you'll probably want to skip it, but if
  346. you are working in RAM or on a hard disk it's doesn't add much to
  347. the compilation time.  Peep should be copied to the same place as
  348. Pascal.
  349.  
  350. However you end up configuring your system, you'll have to
  351. define the Include:  assignment to point to your include file
  352. directory.  This assignment is just the convention I used in the
  353. include files and example programs - it's not part of the compiler
  354. itself, in other words - so if you are willing to modify all the
  355. include files you can use whatever assignment you like.  The only
  356. other assignment of interest is the T:  directory.  This one is
  357. automatically created by AmigaDOS, and since it is used by the
  358. Make script to store intermediate files, assigning it to a RAM:
  359. directory speeds up the whole compilation cycle dramatically.
  360.  
  361.  
  362.  
  363.  
  364.  
  365. ===================================================================
  366.  
  367.                        Compiling a Program
  368.  
  369. ===================================================================
  370.  
  371. Turning a Pascal source file into an executable program is (at
  372. last count) a four step process.  You start off with your source
  373. code (one of the example programs, for example), which probably
  374. ends with ".p".  The first step is to use the compiler to turn
  375. this source file into an equivalent assembly language program.  To
  376. do this, invoke the compiler with the following command format:
  377.  
  378.         Pascal InputPascal OutputAssembly [Directives]
  379.  
  380. "InputPascal" should be replaced with the complete filename
  381. (including path, if necessary) of your source file, and
  382. "OutputAssembly" is the filename (optionally with a path) of the
  383. assembly language output file.  I normally use the extension
  384. ".asm" on the output file.  The directives can be placed anywhere
  385. on the command line, in upper or lower case, and have the
  386. following meaning:
  387.  
  388.      -q      Run in "quiet" mode, i.e. the compiler does not
  389.              write anything to the screen except error
  390.              messages.  This makes it easier to parse the
  391.              output of the compiler in an ARexx script, for
  392.              example.
  393.  
  394.      -s      Small initialization.  Small programs use a
  395.              different initialization routine that does not
  396.              have all the overhead of the standard routine,
  397.              but it means that you will not be able to use any
  398.              Pascal IO (e.g Writeln(), Readln(), etc).
  399.  
  400.      -p      Add code to support the execution profiler.  If you
  401.              use this option, extra information will be included
  402.              in the program to support the execution profiler.
  403.              See the section called Execution Profiling for more
  404.              information.
  405.  
  406.      -$B,
  407.      +$B,
  408.      -$B,
  409.      +$B,
  410.      -$I,
  411.      +$I,
  412.      -$N,    These directives all correspond to the source code
  413.      +$N,    directives with the same letter.  They allow you to
  414.      -$R,    change the default behavior of the compiler.  See
  415.      +$R     the section Compiler Directives for more information.
  416.      -$X
  417.      +$X
  418.  
  419.  
  420. The second step takes the assembly language file and creates a new
  421. file that's slightly more efficient.  This is done using the
  422. program Peep, which is invoked with the following command format:
  423.  
  424.         Peep InputAssembly OutputAssembly
  425.  
  426. I normally use the extension ".s" for assembly files that have
  427. been run through the peephole optimizer, but it is entirely up to
  428. you.
  429.  
  430. The third step takes the .asm or .s file and creates an object
  431. file.  An object file is mostly the same machine-readable
  432. instructions and data as the executable file, but it does not
  433. contain all the routines the final program will need.  The
  434. assembler, in this case Charlie Gibbs' A68k, converts assembly
  435. language programs to object files, and is invoked with the
  436. following command line:
  437.  
  438.         A68k InputAssembly OutputObject
  439.  
  440. A68k is a very powerful, flexible program with lots of options -
  441. be sure to read its documentation file for a complete description.
  442.  
  443. If all these steps finished without errors, you can link the
  444. object file to all the routines in the runtime library it needs to
  445. be an executable program.  The Software Distillery linker, Blink,
  446. handles this part of the process.  It is invoked with the
  447. following command line:
  448.  
  449.         Blink InputObject to OutputExec library PCQ.lib
  450.  
  451. Blink also has many options, and comes with a documentation file
  452. that completely explains them.  Note that you might have to use a
  453. full path to specify where PCQ.lib is - if it's in the LIBS:
  454. directory, for example, you would use LIBS:PCQ.lib instead.
  455.  
  456. You now have, finally, a finished executable file.  That seems
  457. like a lot of steps, and a lot to remember, just to make one
  458. program.  It is.  There are two ways to help automate the
  459. compilation process.  The first and best way is to use PCQ, the
  460. make utility, which is described in PCQ.doc.  The second way is to
  461. use an AmigaDOS script.  Included in the distribution is a script
  462. called Make that compiles a program in the T:  directory, leaving
  463. just the executable program on the disk.  It looks like this:
  464.  
  465.                 .key source
  466.                 Pascal <source>.p T:<source>.asm
  467.                 A68k T:<source>.asm T:<source>.o
  468.                 Delete T:<source>.asm
  469.                 Blink T:<source>.o to <source> library PCQ.lib
  470.                 Delete T:<source>.o
  471.  
  472. You'll note that my preferences for extensions are built in to
  473. this script - the Pascal file ends in .p, the assembly language
  474. file ends in .asm, and the object file ends in .o.  If you prefer
  475. other names, just change the script.  Also note that you might
  476. have to change the script if your compiler, assembler and linker
  477. are not on the normal path, or if PCQ.lib is not in the current
  478. directory (in both cases, just use the complete path in place of
  479. the file name).  To run this script, you just invoke it like this:
  480.  
  481.         Make ProgramName
  482.  
  483. Note that you leave off any extensions.  If everything works OK,
  484. you'll have an executable program called ProgramName left in the
  485. current directory.  One problem with this script is that you can't
  486. use any command line options on the compiler.  I actually have
  487. several different versions of Make scripts that handle all the
  488. combinations I use.
  489.  
  490. The other script, OMake, is virtually the same, except it also
  491. invokes the peephole optimizer to make slightly more efficient
  492. programs.  It looks like:
  493.  
  494.                 .key source
  495.                 Pascal <source>.p T:<source>.asm
  496.                 Peep T:<source>.asm T:<source>.s
  497.                 Delete T:<source>.asm
  498.                 A68k T:<source>.s T:<source>.o
  499.                 Delete T:<source>.s
  500.                 Blink T:<source>.o to <source> library PCQ.lib
  501.                 Delete T:<source>.o
  502.  
  503. Again, you might have to make modifications to suit your set up.
  504. If you are working on a fairly complex project, you will probably
  505. find it convenient to make a set of specialized scripts to
  506. automate the compile-assemble-link process.
  507.  
  508.  
  509.  
  510.  
  511. ===================================================================
  512.  
  513.                         Incompatibilities
  514.  
  515. ===================================================================
  516.  
  517.     PCQ Pascal is incompatible with standard Pascal, and by
  518. extension Turbo Pascal, in several ways.  Briefly, they are:
  519.  
  520.     (1) Sets are not supported.
  521.     (3) The familiar syntax for specifying a single quote
  522.         character constant, which in standard Pascal looks like
  523.         '''', is not supported.  Instead PCQ Pascal uses C escape
  524.         conventions, which are explained in the section called
  525.         Strings.
  526.     (4) The way you open a file is different from Standard Pascal,
  527.         although once it's open the commands are basically the
  528.         same.
  529.  
  530.  
  531. Although PCQ Pascal was not designed to be compatible with Turbo
  532. Pascal, in order to make porting programs easier I'll point out a
  533. few of the more important differences (in addition to those
  534. above).
  535.  
  536.     (1) PCQ Pascal handles strings completely differently from
  537.         Turbo Pascal.  PCQ strings are similar to C strings, which
  538.         are not as easy to manipulate as Turbo strings.  In fact,
  539.         PCQ strings are the most difficult of the three.  They are
  540.         fully explained in the Strings section.
  541.     (2) In a PCQ Pascal function, assigning a value to the
  542.         function name causes you to leave the function.  In Turbo
  543.         Pascal, the function name is treated as a write-only
  544.         variable, and you have to use the Exit command explicitly.
  545.         All the examples in the Pascal Report skirt the issue by
  546.         assigning the value as the last statement.
  547.     (3) Speaking of Exit, Exit in PCQ Pascal quits the program,
  548.         whereas in Turbo it quits the current function or
  549.         procedure.  Turbo's "Exit" is like PCQ's "return", and
  550.         Turbo's "Halt" is like PCQ's "Exit".  Got that?
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557. ===================================================================
  558.  
  559.                            PCQ Programs
  560.  
  561. ===================================================================
  562.  
  563. For the most part, PCQ Pascal programs look very much like
  564. standard Pascal programs.  Apart from the incompatibilities
  565. described above, in fact, PCQ should compile plain Pascal programs
  566. directly.  PCQ makes several extensions to Pascal, however, so in
  567. order to explain them I'll go over what is and is not allowed in
  568. PCQ programs.
  569.  
  570.  
  571.  
  572. ===================================================================
  573.  
  574.                           Reserved Words
  575.  
  576. ===================================================================
  577.  
  578. Reserved words are symbols that cannot be used as identifiers in
  579. your program.  They have special meaning to the compiler, and
  580. cannot be overridden.  The reserved words of PCQ are as follows:
  581.  
  582.             and         array       begin
  583.             case        chip        const
  584.             div         do          downto
  585.             else        end         external
  586.             fast        file        for
  587.             forward     function    goto
  588.             if          in          label
  589.             mod         not         of
  590.             or          packed      private
  591.             procedure   program     record
  592.             repeat      return      set
  593.             then        to          type
  594.             until       var         while
  595.             with
  596.  
  597. As you can see, even the unimplemented stuff is reserved.
  598.  
  599.  
  600.  
  601.  
  602. ===================================================================
  603.  
  604.                      Pascal Program Structure
  605.  
  606. ===================================================================
  607.  
  608. The normal structure of Pascal programs is as follows:
  609.  
  610.  
  611. <Program> ::= Program <Identifier> ; <Block>.  |
  612.               Program <Identifier> (<Identifier List>); <Block>.
  613.  
  614. <Block>   ::= <Declarations> begin <Statements> end |
  615.               begin <Statements> end
  616.  
  617. <Identifier List> ::= <Identifier> , <Identifier List> |
  618.                       <Identifier>
  619.  
  620.  
  621. Does everyone read Backus-Naur?  The idea is that the objects to
  622. the left of the definition sign ::= are being defined by the rule
  623. to the right.  Objects in angle brackets are defined elsewhere in
  624. the list, and the vertical bar character separates alternatives.
  625. Everything else is to be taken literally.  Thus a Pascal program
  626. begins with the literal word Program, followed by an identifier,
  627. followed by a semicolon, followed by a block (whatever that is),
  628. and ending with a period.  On the other hand, it can also consist
  629. of Program followed by an identifier, followed by a left
  630. parenthesis, followed by an identifier list, followed by a right
  631. parenthesis, a semicolon, a block, and finally a period.  Once you
  632. get used to them, BNF diagrams will tell you exactly what you need
  633. to know about the syntax of a program.  BNF grammars can also be
  634. represented as "railroad diagrams", and if this weren't a
  635. text-only document I'd be using them instead.
  636.  
  637. We've left a few things undefined, so we better start filling it
  638. out.
  639.  
  640. <Declarations> ::= <Declaration> , <Declarations> | <Declaration>
  641.  
  642. <Declaration> ::= <Type Declaration>      |
  643.                   <Constant Declaration>  |
  644.                   <Variable Declaration>  |
  645.                   <Label Declaration>     |
  646.                   <Procedure Declaration> |
  647.                   <Function Declaration>
  648.  
  649. Note that standard Pascal imposes an order on the declarations:
  650. it says there should be one constant block, followed by one type
  651. block, etc.  PCQ Pascal removes that restriction, so you can have
  652. as many declarations in whatever order you see fit.
  653.  
  654. Subject to the definition of the rest of those objects, this is
  655. the format for any normal PCQ Pascal program.  There is an
  656. exception (of course):  the separately compilable file.  Turbo
  657. Pascal provides a Unit structure so you can write, compile and
  658. debug units, then use them in many programs.  PCQ provides a
  659. similar, although not as powerful, feature in the form of external
  660. files.  Consider the following extension of our basic rule:
  661.  
  662. <Program> ::= Program <Identifier>; <Block>.  |
  663.               Program <Identifier> (<Identifier List>); <Block>. |
  664.               External ; <Declarations>
  665.  
  666. According to this, an external file is just the reserved word
  667. External followed by a semicolon, then a series of procedures,
  668. functions, whatever.  See the section called External Files for
  669. more information.
  670.  
  671.  
  672.  
  673.  
  674.  
  675. ===================================================================
  676.  
  677.                         Type Declarations
  678.  
  679. ===================================================================
  680.  
  681. Type declarations take the following form:
  682.  
  683. <Type Declaration> ::= Type <Type Definitions>;
  684.  
  685. <Type Definitions> ::= <Type Definition>; <Type Definitions> |
  686.                        <Type Definition>
  687.  
  688. <Type Definition>  ::= <Identifier> = <Type Specification> |
  689.                        <Identifier> = packed <Type Spec>
  690.  
  691. <Type Specification> ::= <Identifier>                      |
  692.                          <Range>                           |
  693.                          ^<Type Specification>             |
  694.                          (<Identifier List>)               |
  695.                          <Array Definition>                |
  696.                          <Record Definition>               |
  697.                          file of <Type Specification>
  698.  
  699. <Range> ::= <Constant Expression> .. <Constant Expression>
  700.  
  701. <Array Definition> ::= array [<Range>] of <Type Specification> |
  702.                        array <Identifier> of <Type Specification>
  703.  
  704. <Record Definition> ::= record <Field Definitions> end
  705.  
  706. <Field Definitions> ::= <Field Definition> |
  707.                         <Field Definition>; <Field Definitions>
  708.  
  709. <Field Definition> ::= <Variable Definition> |
  710.                        <Variant Definition>
  711.  
  712. <Variant Definition> ::= case <Variant Selector> of
  713.                            <Variants>
  714.                          end
  715.  
  716. <Variant Selector> ::= <Identifier> : <Type Specification> |
  717.                        <Type Specification>
  718.  
  719. <Variants> ::= <Variant> | <Variant>; <Variants>
  720.  
  721. <Variant> ::= <Constant Expression> : ( <Variable Definitions> )
  722.  
  723.  
  724. Once you digest the BNF, I think you'll find that straight-
  725. forward.  There is, however, one difference in the way variant
  726. records are defined.  In Standard Pascal, the variant part must
  727. come at the end of the definition, so the reserved word "end"
  728. marks the end of the "case" structure as well as the end of the
  729. record definition.  In PCQ Pascal, on the other hand, each "case"
  730. structure must have its own "end", variants can occur in the
  731. middle of the definition, and there can be several variant parts.
  732. Fields defined after a variant part are located at the end of the
  733. longest variant.
  734.  
  735. In Standard Pascal, the keyword "packed" tells the compiler to
  736. store the variable in the most memory-efficient way possible, even
  737. at the expense of execution speed.  "Packed" is simply ignored by
  738. PCQ Pascal, since all variables are packed automatically.
  739.  
  740. Constant expressions are discussed in the Expressions section
  741. below - for now let's look at the types that are predefined in PCQ
  742. Pascal.
  743.  
  744.  Numeric Types
  745. ---------------
  746.  
  747. PCQ Pascal supports a variety of numeric types that should give
  748. you the flexibility you need to carry out whatever math you might
  749. require.  The types, from smallest to largest range, are:
  750.  
  751. Byte      This is a 1-byte, unsigned integer, capable of holding
  752.           a value from 0 to 255.
  753.  
  754. Short     A Short is a 2 byte (16 bit) signed integer, with a range
  755.           of -32768 to 32767.
  756.  
  757. Word      A Word is a 2 byte (16 bit) unsigned integer, with a
  758.           range of 0 to 65535.
  759.  
  760. Integer   Integer is the largest ordinal type.  It holds a 32-bit
  761.           signed integer, with a range of about -2 billion to 
  762.           2 billion.
  763.  
  764. Real      A floating point value, in Motorola Fast Floating Point
  765.           format.  A Real value is 4 bytes (32 bits), and can
  766.           express floating point values from about 10^19 to about
  767.           about 10^-20, positive or negative.  I'm not sure what
  768.           the accuracy of FFP is, but I wouldn't count on more
  769.           more than 5 or 6 digits.
  770.  
  771. The numeric types are interchangeable in expressions.  If you use
  772. two different types in, for example, a plus expression, the
  773. compiler will automatically promote both values to the smallest
  774. "container type".  A container type is a numeric type whose range
  775. covers both of the arguments.  For example, the result of adding a
  776. Short to an Integer is an Integer.  The result of most binary
  777. operations involving Real values will be a real value.
  778.  
  779.  
  780.  Other Ordinal Types
  781. ---------------------
  782.  
  783. Integers, Shorts and Bytes are all Ordinal types.  This means they
  784. are discrete values that can be represented exactly in binary
  785. (unlike floating point values, which are approximated).  The other
  786. ordinal types are:
  787.  
  788. Char        A one-byte value, stored as the ASCII value.
  789.  
  790. Boolean     Also one byte long, a Boolean value is either -1 (all
  791.             binary ones) for true, or 0 for false.  Anything else
  792.             could produce unpredictable results.  Incidentally,
  793.             the Boolean type can be considered an enumerated type
  794.             with the values True and False.  In most
  795.             implementations False < True and Succ(False) = True,
  796.             but not in PCQ.
  797.  
  798. Enumerated  The values of an enumerated type are specified within
  799.             the program.  If there are 256 or fewer values, the
  800.             enumerated type will be stored in one byte.  If there
  801.             are more, it will be stored in two bytes.  In either
  802.             case, each enumeration is associated with an integer
  803.             value, starting with 0.
  804.  
  805.  
  806.  Pointer Types
  807. ---------------
  808.  
  809. Pointer types hold the address of another variable.  They are
  810. declared as follows:
  811.  
  812.                PointerType = ^<Type Specification>
  813.  
  814. There is an exception in Pascal that allows you to define a
  815. pointer to an undefined type identifier.  In other words, you can
  816. define "RecPtr = ^Rec" before you get around to defining "Rec"
  817. itself.  This is the only time you can use an identifier before it
  818. is declared.  If you use this type of declaration, the identifier
  819. must be defined within the same type declaration block as the
  820. pointer type.
  821.  
  822. Pointers are all 32-bit values.  The predefined pointer constants
  823. are:
  824.  
  825. Address     Address is a special pointer type that is compatible
  826.             with all other pointer types.  It should not be
  827.             dereferenced, but you can use it to avoid cumbersome
  828.             type casts.
  829.  
  830. String      The String type in PCQ is actually defined as a
  831.             pointer to char, although it has other special
  832.             qualities like allowing array-like subscripts.
  833.             Strings are explained in the section called Strings.
  834.  
  835.  
  836.  File Types
  837. ------------
  838.  
  839. Files in PCQ are based on normal AmigaDOS files, but provide
  840. automatic buffering and access to the handy Pascal IO routines
  841. (Writeln, et al).  File variables come in two varieties:
  842.  
  843. Text        A Text file is any normal ASCII file (this
  844.             documentation, for example.
  845.  
  846. Typed Files A typed file, declared as "File of Type", only stores
  847.             values of the given type.  If you issue a Write()
  848.             command on a typed file, PCQ will output the actual
  849.             binary representation of the object to the file.  For
  850.             example, if you have a "File of Integer", the typed
  851.             file will store each Integer as a four-byte binary 
  852.             representation.  A text file, on the other hand, will
  853.             store each Integer as a series of ASCII characters
  854.             from '0' to '9'.  You cannot use Writeln and Readln on
  855.             typed files.
  856.  
  857.  
  858.  
  859.  Type Compatibility
  860. --------------------
  861.  
  862. There are two kinds of type checking.  One is for normal type
  863. compatibility.  That's used for comparing arguments in an
  864. expression, or for formal and actual value parameters.  The second
  865. kind checks for identical types, and is used for more strict
  866. circumstances: in assignment operations and between formal and
  867. actual parameters passed by reference (using the VAR keyword).
  868. PCQ Pascal is, relative to Standard Pascal, generous in its
  869. enforcement of these rules.  For simple type compatibility, the two
  870. types have to pass one of the following tests:
  871.  
  872.       o  They are the same type, or
  873.       o  They are both number types (real, integer, etc), or
  874.       o  They are both arrays with the same size range and the
  875.          element types are compatible, or
  876.       o  They are both pointers to compatible types, or
  877.       o  They are both files of compatible types.
  878.  
  879. Synonym types (e.g. "TYPE ByteSynonym = Byte") are considered
  880. identical types.  For the more strict type identity check, remove
  881. the second rule.
  882.  
  883.  
  884.  
  885.  
  886. ===================================================================
  887.  
  888.                   Constant Declarations
  889.  
  890. ===================================================================
  891.  
  892.  
  893. Constants are normally declared in the Standard Pascal fashion,
  894. which looks like the following in BNF:
  895.  
  896. <Const Block> ::= Const <Const Declarations>;
  897.  
  898. <Const Declarations> ::= <Const Declaration> |
  899.                          <Const Declaration> ; <Const Declarations>
  900.  
  901. <Const Declaration> ::= <Identifier> = <Constant Expression> |
  902.                         <Identifier> : <Type Specification> =
  903.                                         <Typed Constant Value> |
  904.                         <Identifier> : <Mem Spec>
  905.                                         <Type Specification> =
  906.                                         <Typed Constant Value>
  907.  
  908. <Typed Constant Value> ::= <Constant Expression>      |
  909.                            ( <Constant Expressions> ) |
  910.                            @ <Identifier>
  911.  
  912. Constant expressions will be defined below, but you can think of
  913. them as any normal expression that can be completely evaluated
  914. during the compilation (i.e. they use no user-defined functions
  915. and access no variables).
  916.  
  917. Normal constants are easy to understand - they are just like
  918. read-only variables, but they actually take up no memory.  The
  919. constant value is just inserted in the program instead of the
  920. identifier.  Since they are formed by constant expressions, normal
  921. constants can only have a few different types:  integer, real,
  922. char, Boolean, string and array of char.  They can't have any
  923. user-defined type, and can't be record or array types.
  924.  
  925.  
  926.  
  927.  Typed Constants
  928. -----------------
  929.  
  930. That's where typed constants come in.  Typed constants are best
  931. thought of as pre-initialized variables, and they can be of any
  932. type you can define, besides file types.  I have no idea why Turbo
  933. Pascal decided that these objects should be called constants
  934. rather than variables, but I'm following their lead.  Your program
  935. loads with these values already in place, and they will not be
  936. refreshed until the program is reloaded.  They will, therefore,
  937. screw up resident programs if used incorrectly.
  938.  
  939. One handy side effect is that variables local to some procedure
  940. can retain their value throughout a program's execution (like
  941. static variables in C, right?).  In other words, if you declare a
  942. typed constant within a procedure, it will not be accessible to
  943. any code outside of that scope, and it will not lose its value
  944. between calls to the procedure.  Looks like a local, acts like a
  945. global.
  946.  
  947. Declaring typed constants is error prone, and you invariably spend
  948. most of the time counting a list of numbers or trying to match
  949. parentheses or something equally mind-numbing.  Nonetheless, they
  950. are awfully handy.  The syntax corresponds to the second
  951. alternative of the <Const Declaration>, but that doesn't tell the
  952. whole story.  Perhaps it's best to look at some examples:
  953.  
  954.     Type
  955.         ExampleRec = record
  956.                          Field1 : Integer;
  957.                          Field2 : Char;
  958.                          Field3 : Boolean;
  959.                          Field4 : ^Integer;
  960.                          Field5 : Array [-1..1] of Byte;
  961.                      end;
  962.         MultiDim = Array [0..1,0..1] of Integer;
  963.  
  964.     Const
  965.         Message1 : String = "An example string";
  966.         Message2 : Array [0..9] of Char = 'String2   ';
  967.         Message3 : Array [0..9] of Char = ('a','b','c','d','e',
  968.                                            'f','g','h','i','j');
  969.         Value1   : Integer = 456;
  970.         Record1  : ExampleRec =
  971.                         (34, 'r', True, @Value1, (34,56,12));
  972.         Multi1   : MultiDim = ((34,12), (45,15));
  973.  
  974.  
  975. Note that all the "Message" constants and Value1 could also be
  976. specified as normal constants.  Message1 and Value1, in that case,
  977. would not take up any memory, but Messages 2 and 3 would be the
  978. same.  The format of the Message3 declaration is typical for
  979. arrays, but the Message2 format is a special abbreviation for
  980. arrays of char.
  981.  
  982. The <Mem Spec> part of the declaration allows you to define the
  983. category of memory the typed constant will require.  The possible
  984. values are CHIP, which places the constant in memory accessible to
  985. the Amiga's custom chips, and FAST, which places the constant in
  986. the memory area where the CPU faces no competition for access.  If
  987. you are defining constant image or sound data, you can use the
  988. CHIP specification to ensure that the constant is properly located
  989. in memory.  Note that constants without any memory specification
  990. will generally end up in fast RAM, if there is any available.
  991.  
  992. There are several differences between this and Turbo Pascal's
  993. syntax (all, if I may say so, in favor of PCQ).  First of all,
  994. definitions of constant records in Turbo Pascal requires that you
  995. use the field identifier, followed by a colon, the value, and
  996. possibly a semicolon.  That's far too cumbersome for me, so I just
  997. use the same idea as arrays:  you specify each field, separated by
  998. commas, in order.  Turbo uses the more complex syntax to handle
  999. variant records, but PCQ does not allow you to define constant
  1000. records with variants.
  1001.  
  1002. The second difference with Turbo Pascal is that, until version 6.0,
  1003. it only allowed pointer types to be initialized to Nil.  PCQ
  1004. Pascal allows you to initialize a pointer type as Nil, or as the
  1005. address of a preceding global variable or typed constant.  To do
  1006. this, you normally use the '@' operator, which returns the address
  1007. of a specified variable.
  1008.  
  1009. The last difference is that you can use some typed constant values
  1010. in subsequent constant expressions.  You can't use any structured
  1011. types (i.e. records and arrays), but you can use integers, reals,
  1012. and other so-called "simple" types.
  1013.  
  1014.  Standard Constants
  1015. --------------------
  1016.  
  1017. There are several standard constants (i.e. they are built in to
  1018. the compiler itself - you don't have to declare them or use an
  1019. include file).  They are:
  1020.  
  1021.  
  1022. False    False is an enumeration of the type Boolean, and has the
  1023.          value 0.
  1024.  
  1025. MaxInt   MaxInt is the largest integer that can be stored in the
  1026.          32-bit Integer type.  It is: 2,147,483,647, which is
  1027.          $7FFFFFFF in hex.  Thus you can say that the range of an
  1028.          Integer variable is +MaxInt to -MaxInt.
  1029.  
  1030. MaxShort MaxShort is the largest number that can be stored in the
  1031.          16-bit Short type.  It turns out to be 32,767, or $7FFF
  1032.          in hex.  Just as with MaxInt, you can say that the range
  1033.          of a Short variable is +MaxShort to -MaxShort (to be
  1034.          precise, the range is actually +MaxShort to
  1035.          -(MaxShort+1), and MaxInt is analogous).
  1036.  
  1037. MaxWord  MaxWord is the largest number that can be stored in the
  1038.          16-bit Word type.  It is 65,535, or $FFFF in hex.  The
  1039.          range of the word type is therefore 0 to 65,535.
  1040.  
  1041. Nil      Nil is a constant of type Address.  It is defined as
  1042.          something like:
  1043.  
  1044.                 Nil = Address(0);
  1045.  
  1046.          In Standard Pascal, "Nil" is a reserved word.  In PCQ
  1047.          Pascal it isn't reserved, for the simple reason that it
  1048.          doesn't have to be.
  1049.  
  1050. True     True is an enumeration of the type Boolean, and actually
  1051.          has the value -1.  In some cases, any non-zero number
  1052.          will suffice, but the "not" operator will behave
  1053.          erratically if you use weird values.
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060. ===================================================================
  1061.  
  1062.                     Variable Declarations
  1063.  
  1064. ===================================================================
  1065.  
  1066.  
  1067. Variable declarations are handled just like standard Pascal:
  1068.  
  1069. <Var Declaration> ::= Var <Var Definitions> ;
  1070.  
  1071. <Var Definitions> ::= <Var Definition> |
  1072.                       <Var Definition> ; <Var Definitions>
  1073.  
  1074. <Var Definition>  ::= <Identifier List> : <Type Specification> |
  1075.                       <Identifier List> : <Mem Spec> <Type Spec>
  1076.  
  1077. Global variables, i.e. variables declared at the outer-most level,
  1078. are allocated as static memory.  All variables declared within a
  1079. procedure or function are allocated on the stack, so if you are
  1080. writing re-entrant routines, be sure to avoid writing to global
  1081. variables.
  1082.  
  1083. Variables larger than one byte are always allocated on word
  1084. boundaries (not longword boundaries - you'll have to use AllocMem
  1085. to guarantee that).  That's an option in Turbo Pascal, but the
  1086. 68000 makes it mandatory for Amiga programs.  Note that this
  1087. applies within records and arrays as well, so be careful if you
  1088. make assumptions about variable size and location.
  1089.  
  1090. The <Mem Spec> part of a variable definition allows you to specify
  1091. the type of memory required for the variable.  The possible values
  1092. are CHIP and FAST, which place the variable in the Amiga's chip
  1093. and fast RAM, respectively.  Some variables, like image or sound
  1094. data, must be placed in the memory area accessible to the custom
  1095. chips, so you would use the CHIP specification.  The FAST
  1096. specification is included mainly for symmetry, since variables
  1097. tend to be located in fast RAM whenever possible anyway.  These
  1098. memory type specifications can only be used for global variables
  1099. and typed constants, since local variables are always allocated on
  1100. the stack.
  1101.  
  1102. Keep in mind that local variables (not typed constants) disappear
  1103. when you leave the function, so you shouldn't try to access them
  1104. afterward (with a pointer variable, for example).  It just won't
  1105. work.
  1106.  
  1107.  
  1108.  Standard Variables
  1109. --------------------
  1110.  
  1111. There are several variables built-in to PCQ Pascal.  They are
  1112. always available, and are treated like global variables.  They
  1113. are:
  1114.  
  1115. CommandLine     This is a String variable that points to the
  1116.                 command line the user entered (with the name of
  1117.                 the program and any indirection parameters
  1118.                 stripped off).  If the program was executed from
  1119.                 the Workbench, this value is not defined.  Note
  1120.                 that, to be on the safe side, this variable should
  1121.                 be treated as read-only.  Make a copy of it if you
  1122.                 want to modify it.
  1123.  
  1124. ExitAddr        ExitAddr is the location within your program that
  1125.                 a runtime error occurred.  If no error occurred,
  1126.                 its value is undefined.  See the section called
  1127.                 "Exit Procedures" for more information.
  1128.  
  1129. ExitCode        This is the Integer value that will be returned to
  1130.                 AmigaDOS when your program terminates.  It is only
  1131.                 defined within an exit procedure.
  1132.  
  1133. ExitProc        This is an Address variable that holds the address
  1134.                 of the first procedure that will be executed when
  1135.                 your program terminates.  See the section called
  1136.                 "Exit Procedures" for more information.
  1137.  
  1138. HeapError       HeapError is an Address variable that holds the
  1139.                 address of a function to call when New() or
  1140.                 AllocString() is unable to allocate a block of
  1141.                 memory.  See the section called Memory Management
  1142.                 for more information.
  1143.  
  1144. Input           Input is a Text file type.  It corresponds to the
  1145.                 standard input channel of the program, such as the
  1146.                 CLI from which it was run.  PCQ Pascal programs
  1147.                 always establish some sort of standard Input file
  1148.                 unless you specifically tell it not to.  See the
  1149.                 section called Input/Output for more information.
  1150.  
  1151. Output          Output is a Text file type.  It corresponds to the
  1152.                 standard output channel of the program, which in
  1153.                 most cases is the CLI from which it was run.  PCQ
  1154.                 Pascal programs always establish an output file
  1155.                 unless instructed not to.
  1156.  
  1157.  
  1158.  
  1159. ===================================================================
  1160.  
  1161.                Procedure and Function Declarations
  1162.  
  1163. ===================================================================
  1164.  
  1165. Procedures and functions allow you to define common routines
  1166. within a larger block.  Procedures are executed by procedure
  1167. statements, and function are executed when they are used in
  1168. expressions.  The format for procedure and function definitions is
  1169. as follows:
  1170.  
  1171.  
  1172. <Proc Declaration> ::= Procedure <Identifier> ; <Body> |
  1173.                        Procedure <Identifier>
  1174.                                 ( <Formal Params> ); <Body>
  1175.  
  1176. <Body> ::= <Block> | External | Forward
  1177.  
  1178. <Formal Params> ::= <Identifier List> : <Type Specification> |
  1179.                     var <Identifier List> : <Type Specification>
  1180.  
  1181. <Func Declaration> ::= Function <Identifier> :
  1182.                                    <Type Specification> ; <Body> |
  1183.                        Function <Identifier> ( <Formal Params> ) :
  1184.                                    <Type Specification> ; <Body>
  1185.  
  1186.  
  1187. At the risk of being repetitive, keep in mind that you can only
  1188. use procedures where the BNF calls for a <Statement>, and you can
  1189. only use functions where the BNF calls for an <Expression>.
  1190. Unless, of course, you use the $X directive to discard function
  1191. returns (see Compiler Directives for more information).
  1192.  
  1193.  
  1194.  Parameter Passing
  1195. -------------------
  1196.  
  1197. Pascal provides two different kinds of parameter passing.  The
  1198. first type are called value parameters.  These are the normal
  1199. case.  When you pass a parameter by value, the compiler makes a
  1200. copy of the value, and sends that along.  It's as if someone tells
  1201. you to study the Mona Lisa, providing some photographs for you to
  1202. look at.  You can draw a moustache on the photograph, but it won't
  1203. affect the Mona Lisa, and whatever the procedure or function does
  1204. to the parameter will not affect your original values.  When you
  1205. are calling the procedure, you can use any expression (of the
  1206. correct type, of course) as the actual parameter.
  1207.  
  1208. The other type of parameters are called reference parameters.
  1209. They are specified by preceding the parameter name with the
  1210. reserved word "var" in the procedure or function header.  If you
  1211. use reference parameters, it's as if someone tells you to study
  1212. the Mona Lisa, sends you to the Louvre, and tells you where to
  1213. find the painting.  Thus you are working on the original, and had
  1214. better be careful about it.  Reference parameters must be given as
  1215. variable references - they cannot be full expressions.  Also,
  1216. reference parameters have to pass a stricter type compatibility
  1217. test than value parameters do, since we can't have the procedure
  1218. trying to write a 4-byte Integer into a 1-byte space.
  1219.  
  1220. Normally you should prefer value parameters over reference
  1221. parameters (it tends to cut down on bugs), except in three cases.
  1222. The first is when you actually do want to affect the value of a
  1223. variable.  The second is when the parameter is large.  If you use
  1224. a value parameter, the compiler must make a complete copy of it on
  1225. the stack before it calls the routine, which uses both time and
  1226. stack space.  If you use a reference parameter, the compiler just
  1227. puts the address on the stack.  The third case is when the
  1228. parameter is a file type, in which case it must be passed by
  1229. reference.
  1230.  
  1231. PCQ Pascal normally pushes arguments on the stack from left to
  1232. right.  C compilers, because they have to support variable numbers
  1233. of parameters, push arguments from right-to-left.  Therefore if
  1234. you plan to call C routines, you will have to re-order the
  1235. arguments of the call, or declare the external routine with the
  1236. $C+ directive turned on (see Compiler Directives for more
  1237. information).
  1238.  
  1239.  
  1240.  Unnamed Parameters
  1241. --------------------
  1242.  
  1243. If you are familiar with C, you know that language allows you to
  1244. pass any number of parameters to a function.  That causes no end
  1245. of troubles, of course, and certainly doesn't match well with
  1246. Pascal programming principles.  Unfortunately, several shared
  1247. libraries make liberal use of this feature, as does version 2.0 of
  1248. the Amiga operating system.  PCQ Pascal, therefore, allows
  1249. routines to use a variable number of parameters in much the same
  1250. way as C.
  1251.  
  1252. In order to declare a procedure or function that accepts a
  1253. variable number of parameters, you must first of all use C calling
  1254. conventions.  Then you simply use an ellipsis (which looks like
  1255. ...) as the last parameter in the declaration.  For example:
  1256.  
  1257.     {$C+ we must use C calling conventions }
  1258.     Procedure ManyArgs(Format : String; ... );
  1259.  
  1260. The procedure ManyArgs accepts at least one parameter, the Format
  1261. string, plus zero or more extra parameters.  ManyArgs has no way
  1262. of knowing exactly how many arguments it receives:  that
  1263. information must be contained in one of the named parameters, or
  1264. in some other way conveyed to the called routine.
  1265.  
  1266. The extra parameters must be simple types, i.e.  they cannot be
  1267. records, arrays, files, etc.  They can, however, be pointers to
  1268. any of these types, Real values, or any ordinal type like Integer,
  1269. Boolean, enumerated types, etc.
  1270.  
  1271. In order to match the methods used by C compilers, PCQ Pascal
  1272. pushes all ordinal types as long words (i.e.  4 bytes).  C
  1273. normally pushes floating point numbers as doubles (8 bytes), but
  1274. since PCQ does not yet support doubles, it only pushes single
  1275. precision FFP values.
  1276.  
  1277. To access the unnamed parameters, the routine should first
  1278. initialize a variable of type Address using the VA_Start
  1279. procedure.  Once that is done, the VA_Arg function will retrieve
  1280. the arguments in order.  For example, the following routine writes
  1281. all the parameters it was passed, assuming they were all Integers:
  1282.  
  1283.  
  1284.     {$C+}
  1285.     Procedure WriteInts(Num : Short; ... );
  1286.     var
  1287.         ArgPtr : Address;
  1288.         i      : Short;
  1289.     begin
  1290.         VA_Start(ArgPtr);
  1291.         for i := 1 to Num do
  1292.             Writeln(VA_Arg(ArgPtr,Integer));
  1293.     end;
  1294.  
  1295. See below for a description of VA_Start and VA_Arg.
  1296.  
  1297.  
  1298.  
  1299.  Forward Procedures and Functions
  1300. ----------------------------------
  1301.  
  1302. In Pascal, every identifier must be declared before it can be
  1303. used.  This creates problems when procedures or functions are
  1304. mutually dependent, so Pascal allows you to pre-define procedures
  1305. and functions that will be fully defined farther down in the
  1306. source code.
  1307.  
  1308. A forward reference looks just like a normal procedure or function
  1309. declaration, but has the reserved word "Forward" right after the
  1310. header.  The header contains all the information the compiler
  1311. needs to correctly call a routine, so after the forward
  1312. declaration the routine can be used.  When the routine is
  1313. eventually defined, the compiler ensures that it matches up with
  1314. the definition given earlier.  This means that there must be the
  1315. same number of parameters, the parameter types must be the same,
  1316. and if it's a function, the result type must be the same.  Note
  1317. that the actual names of the parameters can be different - only
  1318. their number, order and type are compared.
  1319.  
  1320. A forward reference must be resolved within the same block as it
  1321. was declared, and the same routine cannot be forward-referenced
  1322. more than once.
  1323.  
  1324.  
  1325.  External References
  1326. ---------------------
  1327.  
  1328. External references are very much like forward references - they
  1329. are declarations of routines that aren't actually fully defined.
  1330. The difference is that forward references must be defined later on
  1331. in the same program file, whereas external references are not
  1332. defined in the source file at all.
  1333.  
  1334. The declaration of external references is the same as that of
  1335. forward references, but the reserved word "External" is used in
  1336. place of "Forward".
  1337.  
  1338. External references are used for two main purposes.  First of all,
  1339. they allow you to use procedures and functions defined in External
  1340. files.  All the system routines declared in the include files, for
  1341. example, are actually defined in External files.  They also allow
  1342. you to call routines compiled in a different language, as long as
  1343. you follow some guidelines in parameter passing.  See the section
  1344. called External Files for more information on using external
  1345. routines.
  1346.  
  1347.  
  1348.  Standard Procedures
  1349. ---------------------
  1350.  
  1351. There are several procedures built-in to PCQ Pascal.  They
  1352. include:
  1353.  
  1354.  
  1355.                Close(FileVariable : Any file type)
  1356.  
  1357. The "Close" procedure disassociates the FileVariable from the
  1358. physical disk file, and frees up all the system resources used to
  1359. keep the file open.  See the Input/Output section for more
  1360. information.
  1361.  
  1362.    Dec(V : Any ordinal or pointer) or Dec(V, Amount : Integer)
  1363.  
  1364. Dec (which is short for decrement) subtracts one (or more) from a
  1365. variable.  "Dec(x,n)" is the same as "x := x-n", but slightly more
  1366. efficient.  The variable must be either an ordinal type, like
  1367. Char, Byte, Integer, etc., or a pointer type.  The amount
  1368. parameter, which is optional, must be an integer type - if it is
  1369. not included, the value one is assumed.
  1370.  
  1371. If the variable is an ordinal type, the value is subtracted
  1372. normally.  If the variable is a pointer type, however, Dec()
  1373. multiplies the amount by the size of the type to which the pointer
  1374. refers.  In other words, if you have a pointer p of type ^Integer,
  1375. the statement Dec(p) actually subtracts 4 from the pointer.
  1376.  
  1377.                   Dispose(Variable : ^Anything)
  1378.  
  1379. The "Dispose" procedure frees memory previously allocated with
  1380. "New" (see below).  See the section called Memory Management for
  1381. information on PCQ's memory routines.
  1382.  
  1383.                 Exit or Exit(ReturnCode : Integer)
  1384.  
  1385. Exit, like the AmigaDOS and the C function of the same name,
  1386. terminates the program.  If a return code is specified, it is
  1387. returned to AmigaDOS.  By convention, return codes are normally 5
  1388. for small problems (warnings), 10 for significant problems
  1389. (errors), and 20 when everything goes wrong (failure).  Using Exit
  1390. without a return code is the same as Exit(0), which indicates that
  1391. everything is O.K.
  1392.  
  1393. Exit is the system-safe way to quit a program - you should not
  1394. call AmigaDOS's DOSExit() routine.  When you call Exit, all the
  1395. exit procedures are called in turn.  This includes the standard
  1396. routine that closes all open files and deallocates memory, as well
  1397. as any that you define.
  1398.  
  1399.                Get(var FileVariable : A file type)
  1400.  
  1401. The "Get" procedure moves the file pointer to the next element in
  1402. the file, without actually reading any element in.  The element in
  1403. the file buffer can be accessed through the FileVariable^ syntax.
  1404. See the Input/Output section for details.
  1405.  
  1406.           Inc(VarReference: Ordinal or Pointer type) or
  1407.      Inc(VarReference : Ordinal or Pointer, Amount : Integer)
  1408.  
  1409. The "Inc" command adds an integer Amount to the variable
  1410. VarReference.  If no amount is specified, it is assumed to be 1.
  1411. If the variable is an ordinal type the addition is carried out
  1412. normally, but if it is a pointer type the amount is first
  1413. multiplied by the size of the object to which the pointer refers.
  1414. In other words, Inc(p), where p is a pointer to Integer, actually
  1415. adds 4 (the size of an Integer in bytes) to p.
  1416.  
  1417.                    New(PointerVar : ^Anything)
  1418.  
  1419. The "New" procedure allocates a block of memory equal in size to
  1420. the type to which the variable (which must be a pointer type)
  1421. points.  The address of the newly allocated block will be assigned
  1422. to the variable.  See the section called Memory Management for
  1423. more information.
  1424.  
  1425.                Put(var FileVariable : A file type)
  1426.  
  1427. The "Put" routine advances the file pointer past the current
  1428. element, writing the current element to disk if necessary.  The
  1429. current element can be set through the FileVariable^ syntax.  See
  1430. the section called Input/Output for details.
  1431.  
  1432.  Read(var FileVariable :  Text or File, Variable References....)
  1433.  
  1434. The "Read" procedure inputs information from an AmigaDOS file.
  1435. The FileVariable is optional, and the procedure is one of the very
  1436. few in Pascal that can take a variable number of arguments.  See
  1437. the Input/Output section for more information.
  1438.  
  1439.      Readln(var FileVariable : Text, Variable References....)
  1440.  
  1441. The "Readln" procedure is very similar to "Read", but it can only
  1442. be used on Text files, and after it has read all the arguments it
  1443. requires, it continues to eat characters until it is at the
  1444. beginning of the next line.  See the Input/Output section for more
  1445. information.
  1446.  
  1447.                Reset(var FileVar : File or Text;
  1448.                         FileName : String;
  1449.                       BufferSize : Integer);
  1450.  
  1451. The "Reset" procedure opens a file for reading.  The BufferSize
  1452. parameter is optional.  If you have used the {$I-} directive to
  1453. indicate manual IO checking, you should be sure to check IOResult
  1454. to see if the file opened correctly.  If you are using automatic
  1455. IO checking, the program will terminate with a runtime error if
  1456. the file does not open correctly.  See the Input/Output section
  1457. for more information.
  1458.  
  1459.              Rewrite(var FileVar : File or Text;
  1460.                         FileName : String;
  1461.                       BufferSize : Integer);
  1462.  
  1463. The "Rewrite" procedure opens a file for output, erasing any
  1464. existing file of the same name.  The BufferSize argument is
  1465. optional.  If the file cannot be opened, IOResult will be set to a
  1466. non-zero value.  If you are using automatic IO checking, that will
  1467. cause your program to terminate with a runtime error.  If you are
  1468. using manual IO checking, be sure to look at IOResult to be sure
  1469. the file is open.  See the Input/Output section for more
  1470. information.
  1471.  
  1472.                      Trap(TrapNum : Integer)
  1473.  
  1474. The "Trap" procedure can be used by some debuggers as a sort of
  1475. automatic breakpoint.  If you insert the correct trap, your
  1476. debugger might stop at that location.  Then again it might not.
  1477.  
  1478.                   VA_Start(VAR ArgPtr : Address)
  1479.  
  1480. The VA_Start procedure initializes ArgPtr to point to the first of
  1481. a routine's unnamed arguments.  You can then use VA_Arg to access
  1482. each of the arguments.  You can only use VA_Start within a routine
  1483. that uses a variable number of parameters.
  1484.  
  1485.        Write(FileVariable : Text or File, Expressions....)
  1486.  
  1487. The "Write" procedure outputs information to an AmigaDOS file.
  1488. The FileVariable is optional, and it can take a variable number of
  1489. arguments.  See the Input/Output section for details.
  1490.  
  1491.           Writeln(FileVariable : Text, Expressions....)
  1492.  
  1493. The "Writeln" procedure is very similar to "Write", but it only
  1494. works on Text files, and it terminates the line after writing all
  1495. of its arguments.  Again, see the Input/Output section for more
  1496. information.
  1497.  
  1498.  
  1499.  Standard Functions
  1500. --------------------
  1501.  
  1502. There are also a bunch of functions built in to the Pascal
  1503. compiler.  They are:
  1504.  
  1505.  
  1506.                 Adr(Variable Reference) : Address
  1507.  
  1508. The Adr() function returns the actual address in memory of the
  1509. parameter.  This is equivalent to Turbo Pascal's Addr() function,
  1510. and as in Turbo Pascal you can also use the @ operator.
  1511.  
  1512.            Abs(numeric expression) : same numeric type
  1513.  
  1514. The function call Abs(n) returns n, if n is positive, and -n if n
  1515. is negative.
  1516.  
  1517.             ArcTan(numeric Expression) : Real radians
  1518.  
  1519. The ArcTan() function returns the approximate arctangent of the
  1520. parameter in radians.
  1521.  
  1522.                   Bit(BitNumber) : Mask Integer
  1523.  
  1524. The Bit() function returns an Integer with just the specified bit
  1525. set.  It is equivalent to (1 shl BitNumber).
  1526.  
  1527.                   Chr(numeric expression) : Char
  1528.  
  1529. The Chr() function transforms any numeric type into its ASCII
  1530. character equivalent.
  1531.  
  1532.                    Ceil(Real expression) : Real
  1533.  
  1534. Ceil() returns the least integer greater than or equal to the
  1535. parameter.
  1536.  
  1537.             Cos(numeric expression in radians) : Real
  1538.  
  1539. The Cos() function returns the cosine of the given angle measured
  1540. in radians.
  1541.  
  1542.                EOF(file or Text variable) : Boolean
  1543.  
  1544. EOF returns True if the file is at the end-of-file position, or
  1545. False otherwise.  The EOF function is only valid for files opened
  1546. for input.  See the section called Input/Output for more
  1547. information.
  1548.  
  1549.                    Exp(numeric expression) : Real
  1550.  
  1551. The function Exp(x) returns e raised to the xth power.  In case
  1552. it slipped your mind, e is about 2.71828....
  1553.  
  1554.                  Float(Integer expression) : Real
  1555.  
  1556. The Float() function converts any Integer type expression to its
  1557. floating point representation.  If the integer is fairly large, it
  1558. might be approximated.  Thus "Trunc(Float(IntVar)) = IntVar" is
  1559. not always true.
  1560.  
  1561.                   Floor(Real expression) : Real
  1562.  
  1563. The Floor() function returns the largest whole number less than or
  1564. equal to the parameter.
  1565.  
  1566.                         IOResult : Integer
  1567.  
  1568. The IOResult() function checks to see if any errors have occurred
  1569. since the last time you checked.  Normally, PCQ Pascal inserts
  1570. statements to check the IOResult automatically, but if you have
  1571. set IO checking off (using the {$I-} directive), you'll have to
  1572. check it explicitly.  The act of checking it erases it, so if you
  1573. need to re-use it you'll have to save it in a variable.  See the
  1574. Input/Output section for more information.
  1575.  
  1576.                   Ln(numeric expression) : Real
  1577.  
  1578. The Ln() function returns the natural logarithm (i.e. the
  1579. logarithm to the base e) of the parameter.
  1580.  
  1581.                  Odd(numeric expression) : Boolean
  1582.  
  1583. The Odd() function returns TRUE if its argument is odd, and FALSE
  1584. otherwise.
  1585.  
  1586.                Open(fname      : String;
  1587.                     var fvar   : file or Text;
  1588.                     BufferSize : Integer) : Boolean;
  1589.  
  1590. Open is the function form of the Rewrite procedure.  It opens a
  1591. file for output, erasing any existing file with the same name.  If
  1592. the file opens correctly, Open returns True.  If not, it returns
  1593. False.  The BufferSize parameter is optional.  See the section
  1594. called Input/Output for more information.
  1595.  
  1596.                 Ord(Ordinal expression) : Integer
  1597.  
  1598. The Ord() function returns the ordinal value of the argument as an
  1599. Integer.  In other words, it can convert Chars, Booleans, and
  1600. enumerated types into their numeric equivalents.  Since it
  1601. actually changes the type of the argument into an Integer it is
  1602. referred to as a transfer function.
  1603.  
  1604.                Pred(Ordinal expression) : same type
  1605.  
  1606. The Pred() function returns the next least ordinal value in the
  1607. same type.  For example, Pred(2) is 1.  If the argument is the
  1608. lowest value within the type (such as Pred(ByteVar) where ByteVar
  1609. is zero), its behavior is undefined.
  1610.  
  1611.              ReOpen(fname      : String;
  1612.                     var fvar   : file or text;
  1613.                     buffersize : Integer) : Boolean
  1614.  
  1615. ReOpen is the function form of Reset.  It opens a file for
  1616. reading, and returns True if everything went O.K.  If for any
  1617. reason the file did not open correctly, ReOpen returns False.  The
  1618. BufferSize parameter is optional, and can be any amount.  See the
  1619. section called Input/Output for more information.
  1620.  
  1621.                  Round(Real expression) : Integer
  1622.  
  1623. The Round() function rounds a real expression to the nearest
  1624. Integer.  It is actually implemented as Trunc(value + 0.5), so it
  1625. takes somewhat longer to execute than the Trunc function.  Also,
  1626. it always rounds 0.5 up.
  1627.  
  1628.             Sin(numeric expression in radians) : Real
  1629.  
  1630. The Sin() function computes the sine for the given angle measured
  1631. in radians.
  1632.  
  1633.                 SizeOf(Type Identifier) : Integer
  1634.  
  1635. The SizeOf() function returns the actual size of the given type.
  1636. Note that the type must be specified as a single identifier.
  1637.  
  1638.                Sqr(numeric expression) : same type
  1639.  
  1640. The function Sqr(x) returns x*x.
  1641.  
  1642.                  Sqrt(numeric expression) : Real
  1643.  
  1644. The function Sqrt(x) returns the square root of x.  In other
  1645. words, Sqrt(x) * Sqrt(x) = x.
  1646.  
  1647.                Succ(Ordinal expression) : same type
  1648.  
  1649. The Succ() function returns the next greater ordinal value within
  1650. the same type.  If that value is not defined (for example, Succ(n)
  1651. where n is the largest enumeration within a type), the function is
  1652. not defined.
  1653.  
  1654.             Tan(numeric expression in radians) : Real
  1655.  
  1656. Returns the tangent of the angle measured in radians.  If the
  1657. parameter is an odd multiple of Pi/2, this function will take on
  1658. meaningless values (the tangent function is undefined at odd
  1659. multiples of Pi/2).
  1660.  
  1661.                  Trunc(real expression) : Integer
  1662.  
  1663. The Trunc() function returns the integer portion of a floating
  1664. point number.  It is the fastest way to convert a real value to an
  1665. Integer value.
  1666.  
  1667.      VA_Arg(VAR ArgPtr : Address; Simple Type Spec) : simple type
  1668.  
  1669. The VA_Arg function returns the next unnamed argument, then
  1670. advances ArgPtr to the following argument.  You must call VA_Start
  1671. first to initialize ArgPtr.  See the section called Type
  1672. Declarations for information on Type Specifications.
  1673.  
  1674.  
  1675.  
  1676. ===================================================================
  1677.  
  1678.                         Label Declarations
  1679.  
  1680. ===================================================================
  1681.  
  1682. Labels must be declared in the declaration section before they can
  1683. be used in the program.  The label declaration section has the
  1684. following form:
  1685.  
  1686. <Label Declarations> ::= Label <Identifiers> ;
  1687.  
  1688. <Identifiers> ::= <Identifier> | <Identifier> , <Identifiers>
  1689.  
  1690. Note that Standard and Turbo Pascal also allow labels to have
  1691. numeric values, but PCQ Pascal only allows normal identifiers to
  1692. be used.  If you run across a program with numeric labels, you can
  1693. just put some letter on the front to make them legal identifiers.
  1694. Perhaps a better solution would be to trash the program.
  1695.  
  1696.  
  1697.  
  1698.  
  1699.  
  1700. ===================================================================
  1701.  
  1702.                            Expressions
  1703.  
  1704. ===================================================================
  1705.  
  1706. PCQ Pascal accepts expressions very similar in form to just about
  1707. all Pascal implementations.  It's probably very familiar to you,
  1708. but just to be on the safe side, we'll define it.  Let's start off
  1709. with the constants accepted by PCQ:
  1710.  
  1711.  
  1712. <digit>         ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
  1713.  
  1714. <digits>        ::= <digit> | <digit> <digits>
  1715.  
  1716. <binary digit>  ::= 0 | 1
  1717.  
  1718. <binary digits> ::= <binary digit> | 
  1719.                     <binary digit> <binary digits>
  1720.  
  1721. <hex digit>     ::= <digit> | a | b | c | d | e | f
  1722.  
  1723. <hex digits>    ::= <hex digit> | <hex digit> <hex digits>
  1724.  
  1725. <Float Const>   ::= <Float Value> | <Float Value> <Float Scale>
  1726.  
  1727. <Float Value>   ::= <digits> | <digits> . <digits>
  1728.  
  1729. <Float Scale>   ::= E <Sign> <digits> | E <digits>
  1730.  
  1731. <Sign>          ::= + | -
  1732.  
  1733. <Integer Const> ::= <digits> | $ <hex digits> | % <binary digits>
  1734.  
  1735. <Char Value>    ::= <ASCII char> | \ <escape sequence>
  1736.  
  1737. <Char Values>   ::= <Char Value> | <Char Value> <Char Values>
  1738.  
  1739. <Number Const>  ::= <Integer Const> | <Float Const>
  1740.  
  1741. <Char Const>    ::= ' <Char Value> '
  1742.  
  1743. <String Const>  ::= " <Char Values> "
  1744.  
  1745. <Char Array Const> ::= ' <Char Values> '
  1746.  
  1747.  
  1748. That should confuse things a bit.  What it says is that whenever
  1749. the compiler expects an integer, you can use decimal, hexadecimal
  1750. or binary representation.  It also says that you can use C-style
  1751. escape sequences for any text constant - these escape values are
  1752. discussed in the Strings section.  Note that previous versions of
  1753. PCQ Pascal did not support floating point numbers of the form
  1754. "2.5e6", but the current version does.
  1755.  
  1756. So how are these things grouped into complete expressions?
  1757. Consider the following definitions:
  1758.  
  1759. <expression> ::= <simple> <rel op> <simple> | <simple>
  1760.  
  1761. <rel op>     ::= = | <> | < | > | <= | >=
  1762.  
  1763. <simple>     ::= <term> <add op> <term> | <term>
  1764.  
  1765. <add op>     ::= + | - | or | xor
  1766.  
  1767. <term>       ::= <factor> <mul op> <factor> | <factor>
  1768.  
  1769. <mul op>     ::= * | / | div | mod | and | shr | shl
  1770.  
  1771. <factor>     ::= <Number Const>         |
  1772.                  <Sign> <Number Const>  |
  1773.                  <Char Const>           |
  1774.                  <String Const>         |
  1775.                  <Char Array Const>     |
  1776.                  <Variable Reference>   |
  1777.                  @ <Variable Reference> |
  1778.                  not <factor>           |
  1779.                  ( <Expression> )       |
  1780.                  <Function call>
  1781.  
  1782.  
  1783. What does all this mean?  It means that expressions are built up
  1784. from factors, the basic blocks of an expression.  A factor can be
  1785. a constant, a variable, a parenthesized expression, and all the
  1786. other things listed.  The following examples are all factors:
  1787.  
  1788.                                 23
  1789.                            (4.0 - 2.3)
  1790.                             %01000001
  1791.                                'a'
  1792.                      RecordPtr^.Field1[45,23]
  1793.                               @Var1
  1794.                             Abs(Var2)
  1795.  
  1796. Factors can have a unary operator (an operator that applies to
  1797. only one value, unlike binary operators that apply to two).  They
  1798. are:
  1799.  
  1800.         @   This operator is the address-of operator.  It returns
  1801.             the address of the variable reference immediately
  1802.             following.  It is equivalent to the Adr() function.
  1803.         -   Sign negation.  Takes the negation of the factor
  1804.             following it.
  1805.         +   Sign identity.  It is accepted, but has no affect.
  1806.        not  Boolean or bitwise negation.  If the factor is a
  1807.             Boolean value, this returns the opposite.  If it is an
  1808.             integer type, it returns the bitwise compliment.
  1809.  
  1810. These factors are built into terms.  Terms are either the same as
  1811. factors, or two factors with a multiplicative operator between
  1812. them.  The multiplicative operations are the following:
  1813.  
  1814.         *   Multiplication
  1815.         /   Floating point division.  Both arguments to this
  1816.             operator are converted to floating point before the
  1817.             operation takes place.
  1818.        div  Integer division.  Both arguments to this operator
  1819.             are converted to integer forms before the operation
  1820.             takes place.
  1821.        mod  The remainder operation.  Both arguments are
  1822.             converted to integers if necessary.
  1823.        and  Logical AND function.  If both arguments are Boolean
  1824.             values and the left factor evaluates to FALSE, this
  1825.             operation will "short-circuit".  Any Real factors are
  1826.             converted to Integers.
  1827.        shl  Shift left.  Shifts the bits in the left operand the
  1828.             number of positions given by the right operand.  Both
  1829.             arguments are converted to Integers if necessary.
  1830.        shr  Shift right.  Shifts the bits in the left operand
  1831.             the number of positions given by the right operand.
  1832.             This is a logical shift, not arithmetic, so the
  1833.             left-most bit is assigned 0.  Thus if you shift a
  1834.             negative number in order to do division, you will get
  1835.             nonsense results (use div instead - it will use shifts
  1836.             when possible).  Both arguments are converted to
  1837.             Integers.
  1838.  
  1839. Terms, in turn, are built into simple expressions.  Simple
  1840. expressions are either the same thing as terms, or two terms
  1841. grouped by an addition operator.  The addition operators are:
  1842.  
  1843.         +   Adds the two operands.
  1844.         -   Subtracts the second operand from the first.
  1845.         or  Logical OR.  If both operands are Boolean values and
  1846.             the left operand evaluates to TRUE, the right operand
  1847.             is not evaluated.  Both arguments are converted to
  1848.             Integers if necessary.
  1849.        xor  Exclusive OR.  Generates the left term exclusive ORed
  1850.             with the right term.  This never short circuits.  If
  1851.             either argument is a Real value, it is converted to an
  1852.             Integer.
  1853.  
  1854. These simple expressions are built into complete expressions.
  1855. Expressions are either the same thing as simple expressions, or
  1856. two simple expressions grouped by a relative operator.  These
  1857. operators produce Boolean results, and are defined as:
  1858.  
  1859.         =   Returns TRUE iff the two arguments are equal.
  1860.         <>  Returns TRUE iff the two arguments are not equal.
  1861.         >   Returns TRUE iff the left argument is greater than the
  1862.             right argument.
  1863.         <   Returns TRUE iff the left argument is less than the
  1864.             right argument.
  1865.         >=  Returns TRUE iff the left argument is either greater than
  1866.             or equal to the right argument (that's only takes one
  1867.             comparison, by the way).
  1868.         <=  Returns TRUE iff the left argument is either less than
  1869.             or equal to the right argument.
  1870.  
  1871.         (iff is shorthand for "if and only if")
  1872.  
  1873.  
  1874.  Evaluation Order & Short Circuits
  1875. --------------------------------------------------
  1876.  
  1877. The normal rules of math are built-in to the grammar for
  1878. expressions.  The unary operators are evaluated first, then all
  1879. the multiplicative operations, the additive operations, and
  1880. finally the relative operations.  Thus the precedence looks like
  1881. this:
  1882.  
  1883.         Operator              Precedence
  1884.       -------------------------------------
  1885.         @,not,unary +/-     First (highest)
  1886.  
  1887.         *,/,div,mod,
  1888.         and,shr,shl         Second
  1889.  
  1890.         +,-,or,xor          Third
  1891.  
  1892.         =,<>,<,>,>=,<=      Fourth (lowest)
  1893.  
  1894. All expressions in parentheses are, of course, evaluated first.
  1895. Also, keep in mind that all of these operators are left
  1896. associative - in other words, a factor between two operators of
  1897. equal precedence is bound to the one on the left (e.g.  "x+y+z" is
  1898. treated as "(x+y)+z").
  1899.  
  1900. You should not make any conclusions about the order in which the
  1901. two operands to a binary operator are evaluated.  If you have the
  1902. expression "function1 + function2" in your program, for example,
  1903. there is no telling which function would be evaluated first.
  1904.  
  1905. The exception to that rule is for Boolean equations, but only if
  1906. you are using short-circuit evaluations (the default).  What is a
  1907. short circuit?  Imagine you have the expression "A or B" in your
  1908. program.  If the program evaluates A and finds that it is True, it
  1909. already knows the final value of the entire expression.  Therefore
  1910. there's no point in evaluating B.  The analogous case for "A and
  1911. B" occurs when A evaluates to False.  You can be sure, in a
  1912. Boolean expression, that the operands of "and" and "or" will be
  1913. evaluated left-to-right.
  1914.  
  1915. Short-circuit evaluations are often faster than normal ones, but
  1916. they have the added benefit of protecting the programmer.  For
  1917. example, the statement:
  1918.  
  1919.         if OpenMyWindow(w) and (w^.Width = whatever) then ....
  1920.  
  1921. ... would be a problem without short-circuit evaluations because,
  1922. for example, the variable w might not be defined if the function
  1923. call fails.  The value of the function would not change, but if
  1924. w pointed to an odd address it could cause a guru.  With
  1925. short-circuit evaluations, the second factor would not be
  1926. evaluated unless the first returned True.
  1927.  
  1928.  
  1929.  Constant Expressions
  1930. ----------------------
  1931.  
  1932. Constant expressions are the same as normal expressions, but must
  1933. be completely evaluated at compile time.  Thus they can't use any
  1934. external functions or variable references, but can use all the
  1935. same operators and the standard functions (i.e. the ones built-in
  1936. to the compiler).
  1937.  
  1938.  
  1939.  Variable References
  1940. ---------------------
  1941.  
  1942. Variable references can get awfully complex, what with pointers
  1943. and records and arrays and so forth.  The basic syntax is as
  1944. follows:
  1945.  
  1946. <Variable Reference> ::= <Variable Mark> |
  1947.                          <Variable Mark> <Selectors>
  1948.  
  1949. <Variable Mark> ::= <Variable ID> |
  1950.                     <Type ID> ( <Variable Reference> )
  1951.  
  1952. <Selectors>  ::= <Selector> | <Selector> <Selectors>
  1953.  
  1954. <Selector>   ::= ^ | .<Field Id> | [ <Index Expressions> ]
  1955.  
  1956.  
  1957. Generally speaking, a variable reference will consist of the
  1958. identifier of a global or local variable, followed by any number
  1959. of selectors in any combination.  The other possibility, which is
  1960. somewhat different as of version 1.2 of the compiler, is that you
  1961. can place a type cast somewhere in the middle of all this.  The
  1962. following are all examples of variable references:
  1963.  
  1964.         Var1
  1965.         Var1^
  1966.         Var1^.Field1[34,56]
  1967.         Type2(Var1)^.Field2^^[23]
  1968.  
  1969. If you start writing code that looks like the last example, you
  1970. should get some rest.
  1971.  
  1972.  
  1973.  
  1974.  
  1975. ===================================================================
  1976.  
  1977.                           Statements
  1978.  
  1979. ===================================================================
  1980.  
  1981. Statements are the meat and potatoes of programs - they are what
  1982. goes between begin and end.  They have the following form:
  1983.  
  1984. <Statement>   ::= <If Statement>         |
  1985.                   <While Statement>      |
  1986.                   <Repeat Statement>     |
  1987.                   <For Statement>        |
  1988.                   <Case Statement>       |
  1989.                   <With Statement>       |
  1990.                   <Compound Statement>   |
  1991.                   <Assignment Statement> |
  1992.                   <Procedure Call>       |
  1993.                   <Return Statement>     |
  1994.                   <Goto Statement>
  1995.  
  1996.  
  1997.  If Statements
  1998. ---------------
  1999.  
  2000. The if statement allows you to test alternatives.  It has the
  2001. following form:
  2002.  
  2003. <If Statement> ::= if <Boolean Expr> then <Statement> |
  2004.                    if <Boolean Expr> then <Statement>
  2005.                                      else <Statement>
  2006.  
  2007. If the Boolean expression evaluates to True, the statement
  2008. following the word "then" is executed.  If the Boolean expression
  2009. evaluates to False, the statement in the else clause, if one
  2010. exists, is evaluated.  If no else clause exists, execution
  2011. continues with the statement following the "if" statement.
  2012.  
  2013. There is an ambiguity here - consider the following fragment:
  2014.  
  2015.         if Expr then if Expr then Statement1 else Statement2
  2016.  
  2017. To which "if" test does the else clause apply?  PCQ, like most
  2018. implementations, always attaches the else part to the most recent
  2019. "if".
  2020.  
  2021. If the Boolean expression can be evaluated at compile-time (if
  2022. it's a constant, in other words), and it evaluates to FALSE, no
  2023. code is generated for the entire statement.  You can, therefore,
  2024. enclose debugging code in an "if" statement, and set a global
  2025. constant to determine whether the code is included or not.  Since
  2026. you can use any constant expression, you could even use debugging
  2027. levels.  For example:
  2028.  
  2029.         if DEBUGGING_LEVEL > 2 then begin
  2030.             ...
  2031.         end;
  2032.  
  2033. This statement would only generate code if the constant
  2034. DEBUGGING_LEVEL was greater than 2.  If it was a variable instead
  2035. of a constant, the code would always be generated.
  2036.  
  2037.  
  2038.  While Statements
  2039. ------------------
  2040.  
  2041. The "while" statement is one of several that allow you to loop.
  2042. It has the following form:
  2043.  
  2044. <While Statement> ::= while <Boolean Expr> do <Statement>
  2045.  
  2046. At the beginning of the loop, the Boolean expression is evaluated.
  2047. If it evaluates to True, the statement part is executed.  When
  2048. that finishes, the expression is re-evaluated, and the process
  2049. continues until the expression evaluates to False.  Once that
  2050. happens, execution continues with the statement following the
  2051. while statement.
  2052.  
  2053.  
  2054.  Repeat Statements
  2055. -------------------
  2056.  
  2057. The "repeat" statement provides a slightly different form of
  2058. looping.  It has the following form:
  2059.  
  2060. <Repeat Statement> ::= repeat <Statements> until <Boolean Expr>
  2061.  
  2062. <Statements> ::= <Statement> | <Statement> ; <Statements>
  2063.  
  2064. When the repeat statement is encountered, the statement part is
  2065. executed, then the Boolean expression is evaluated.  If the
  2066. expression evaluates to False, the statement part is executed
  2067. again.  If the expression evaluates to True, execution continues
  2068. at the following statement.  Note that "repeat" loops always
  2069. execute at least once, whereas "while" loops might not execute at
  2070. all.  Also note that the <Statements> part can actually be empty.
  2071.  
  2072.  
  2073.  For Statements
  2074. ----------------
  2075.  
  2076. The "for" statement provides a third type of looping, for
  2077. occasions when you know exactly how many iterations of the loop
  2078. you want to execute.  It has the following form:
  2079.  
  2080. <For Statement> ::= for <Variable Reference> :=
  2081.                         <Expression> <Direction>
  2082.                         <Expression> do <Statement>
  2083. <Direction> ::= to | downto
  2084.  
  2085. Note that this is different from the PCQ version 1.1.  When a
  2086. "for" loop is encountered, the first expression (the initial
  2087. value) is evaluated, and its value is stored in the variable
  2088. reference (called the index).  Then the index is compared to the
  2089. second expression (the final value).  If the direction is "to",
  2090. and the index is less than or equal to the final value, the
  2091. statement part is executed.  At the end of that, the index is
  2092. incremented by one and again tested against the final value.  This
  2093. goes on until the index is greater than the final value, at which
  2094. time execution moves on to the next statement.
  2095.  
  2096. If the direction is "downto", the same thing happens, except the
  2097. index is decremented at each pass, and looping continues until the
  2098. index is less than the final value.
  2099.  
  2100. Note that the "for" loop might not execute at all, if the initial
  2101. value is larger than the final value (for "to" loops, or vice
  2102. versa for "downto" loops).  Also note that the final value is
  2103. fully evaluated each time through the loop, so if it's a complex
  2104. expression you might want to store it in a variable before the
  2105. "for" statement.
  2106.  
  2107. You can always use a "while" or "repeat" loop in place of a "for"
  2108. loop, and in fact the "for" loop is least often used.  Niklaus
  2109. Wirth, the guy who designed Pascal and Modula-2, actually left the
  2110. statement out of his latest language (Oberon).
  2111.  
  2112. It is considered an error to modify the index variable within the
  2113. loop, but PCQ Pascal doesn't enforce it.  That doesn't make it a
  2114. good idea, of course.
  2115.  
  2116.  
  2117.  Case Statements
  2118. -----------------
  2119.  
  2120. The Case statement is used to test a value against a series of
  2121. alternatives, and process instructions accordingly.  It has the
  2122. following form:
  2123.  
  2124. <Case Statement> ::= case <Expression> of <Alternatives> end |
  2125.                      case <Expression> of <Alternatives>
  2126.                                        else <Statement> end
  2127.  
  2128. <Alternatives> ::= <Alternative> | <Alternative> ; <Alternatives>
  2129.  
  2130. <Alternative> ::= <Case Vals> : <Statement>
  2131.  
  2132. <Case Vals> ::= <Case Val> | <Case Val> , <Case Vals>
  2133.  
  2134. <Case Val>  ::= <Const Expr> | <Const Expr> .. <Const Expr>
  2135.  
  2136. When the case statement is executed, the expression is evaluated.
  2137. It is then compared against all of the cases and ranges until it
  2138. matches one, at which point the associated statement is executed.
  2139. If none of the alternatives match, the else statement is executed,
  2140. if there is one.  If not, execution just continues with the
  2141. statement following the case statement.
  2142.  
  2143. Note that the expression is only evaluated once, so a case
  2144. statement can be more efficient than an equivalent series of "if"
  2145. statements.  Also note that one statement (at most) from the case
  2146. statement is executed - it's not like C, where execution falls
  2147. through until you tell it to knock it off.
  2148.  
  2149.  
  2150.  With Statements
  2151. -----------------
  2152.  
  2153. The With statement allows to specify a record variable to which a
  2154. statement will apply.  Within the statement you can abbreviate
  2155. references to the record's fields by specifying just the field
  2156. name.  That saves you some typing, and the compiler generates
  2157. somewhat more efficient code.  It serves no functional purpose.
  2158. The format of a With statement is as follows:
  2159.  
  2160. <With Statement> ::= with <Expressions> do <Statement>
  2161.  
  2162. <Expressions> ::= <Expression> | <Expression> , <Expressions>
  2163.  
  2164. If you specify more than one record (separated by commas), the
  2165. compiler treats it like nested with statements, with the first
  2166. record listed at the outermost scope and the last one at the
  2167. innermost.
  2168.  
  2169. In the statement, any references to fields will be considered to
  2170. apply to the innermost record to which it applies.  Ambiguities
  2171. can be cleared up by using the full record specification.
  2172.  
  2173. With statements are especially handy when the record reference is
  2174. long and convoluted - it will only be executed once, which
  2175. increases efficiency.  The other time it comes in especially handy
  2176. is filling in values in a record.  It doesn't always improve the
  2177. program's efficiency, but it saves a lot of typing.
  2178.  
  2179. If you are executing under a with statement of the form "with p^
  2180. do ...", it is considered an error to alter the value of p.  For
  2181. example, it is an error to free the memory of a record in a "with"
  2182. statement referencing the record.  This error is not detected by
  2183. PCQ Pascal, but it's a good idea to avoid it.
  2184.  
  2185.  
  2186.  Compound Statements
  2187. ---------------------
  2188.  
  2189. The compound statement allow you to use a series of statements in
  2190. any situation that calls for at least one statement.  It has the
  2191. following form:
  2192.  
  2193. <Compound Statement> ::= begin <Statements> end
  2194.  
  2195. A compound statement can in fact be used wherever a statement is
  2196. allowed, and the compound statement by itself generates no extra
  2197. code.  In other words, surrounding a group of expressions with
  2198. "begin" and "end" will not change the code the compiler produces -
  2199. it just clarifies your purpose.
  2200.  
  2201.  
  2202.  Assignment Statements
  2203. -----------------------
  2204.  
  2205. Assignment statements are used to set the value of variables.
  2206. They have the following form:
  2207.  
  2208. <Assignment Statement> ::= <Variable Reference> := <Expression>
  2209.  
  2210. Remember that the type of the variable must match the type of the
  2211. expression identically (see the section called Type Declarations
  2212. for the specific rules).
  2213.  
  2214.  
  2215.  Procedure Calls
  2216. -----------------
  2217.  
  2218. Procedure calls transfer execution to a pre-defined routine,
  2219. passing parameters as required.  They have the following form:
  2220.  
  2221. <Procedure Call> ::= <Identifier> |
  2222.                      <Identifier> ( <Actual Params> )
  2223.  
  2224. <Actual Params> ::= <Actual Param> |
  2225.                     <Actual Param> ; <Actual Params>
  2226.  
  2227. <Actual Param> ::= <Expression>
  2228.  
  2229. Procedures are different from functions in that functions return a
  2230. value, and are callable only from expressions.  Procedures do not
  2231. return a value, and are callable only from statements.  You can
  2232. instruct PCQ Pascal to ignore these differences with the $X+
  2233. directive, which lets you treat functions as if they were
  2234. procedures.
  2235.  
  2236. When a procedure statement is executed, each actual parameter is
  2237. evaluated and pushed on the stack, in left to right order.
  2238. Because C uses variable numbers of parameters, it pushes actual
  2239. parameters on the stack in right to left order.  Therefore if you
  2240. plan to call a C routine you will need to reverse the order of the
  2241. parameters, or be sure the $C+ directive is active when the
  2242. external routine is defined.
  2243.  
  2244.  
  2245.  Return Statements
  2246. -------------------
  2247.  
  2248. Normally, execution of a procedure continues until the end of the
  2249. procedure, when execution returns to the caller.  The "return"
  2250. statement allows you to escape the current procedure immediately.
  2251. It has the following very simple form:
  2252.  
  2253.     <Return Statement> ::= return
  2254.  
  2255. The "return" statement is only valid within procedures.  It is not
  2256. valid within functions because they must return a value - the
  2257. analogous statement in a function is an assignment to the function
  2258. identifier, which causes the function to return immediately.  The
  2259. "return" statement is also not valid in the main body of the
  2260. program, because it would cause the program to terminate.  Instead
  2261. you must explicitly terminate the program with the Exit statement.
  2262.  
  2263.  
  2264.  
  2265.  Goto Statements
  2266. -----------------
  2267.  
  2268. The "goto" statement immediately transfers execution to a defined
  2269. label.  It should be used with extreme care, and if possible
  2270. avoided.  Its form is:
  2271.  
  2272. <Goto Statement> ::= goto <Identifier>
  2273.  
  2274. Standard Pascal requires that a goto label should be a series of
  2275. digits, and Turbo Pascal extends that definition to allow
  2276. identifiers to be used as labels.  PCQ Pascal takes the next
  2277. logical step by requiring that labels be identifiers, not numbers.
  2278.  
  2279. Most programmers will tell you that the "goto" statement is simply
  2280. bad programming practice, because it makes programs difficult to
  2281. understand and debug.  There are, however, other problems.  For
  2282. instance, if you "goto" from inside a "for" loop to outside of the
  2283. loop, you will confuse your program's stack (until you leave the
  2284. routine).  Similar things happen for the "with" statement.  I
  2285. won't even bother to tell you the havoc that would ensue if you
  2286. jumped into a "for" loop from outside.
  2287.  
  2288. The moral of the story is: try to avoid them.
  2289.  
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  
  2295. ===================================================================
  2296.  
  2297.                       Input/Output
  2298.  
  2299. ===================================================================
  2300.  
  2301.  
  2302.  Pascal IO
  2303. -----------
  2304.  
  2305. You can think of the Pascal IO routines as an interface to the
  2306. AmigaDOS routines.  The Pascal IO routines all use AmigaDOS for
  2307. the actual reading and writing, so if you felt like it you could
  2308. just use an AmigaDOS file instead.
  2309.  
  2310. Pascal IO does have several advantages, however.  First of all,
  2311. all PCQ Pascal files are buffered, which means that reads and
  2312. writes do not necessarily have to access AmigaDOS each time.  That
  2313. speeds things up a bit.
  2314.  
  2315. The other advantage you get is the use of the Pascal Read, ReadLn,
  2316. Write and Writeln routines, which can be awfully handy.
  2317.  
  2318. When you declare a file in your program, as either a "File of Some
  2319. Type" or as "Text", you are in effect allocating a record.  That
  2320. record, if its fields were accessible, would look like:
  2321.  
  2322.      PCQFile = record
  2323.          Handle      : An AmigaDOS file handle
  2324.          Next        : A pointer to the next open Pascal file
  2325.          Buffer      : The address of the file's buffer
  2326.          Current     : The position in the buffer at which the
  2327.                        next read or write will take place.
  2328.          Last        : The Last position of a read
  2329.          Max         : The address of the end of the buffer+1
  2330.          RecSize     : The size of the file elements
  2331.          Interactive : A Boolean value - True means the file
  2332.                        is attached to a CLI window.
  2333.          EOF         : A Boolean value
  2334.          Access      : A Short value, either MODE_NEWFILE or
  2335.                        MODE_OLDFILE
  2336.      end;
  2337.  
  2338.  
  2339.  
  2340.  Text and Typed Files
  2341. ----------------------
  2342.  
  2343. Pascal has two very different types of files.  The normal kind of
  2344. file is called a typed file, and is declared with a type
  2345. specification of the form:
  2346.  
  2347.                   FileVar : File of ElementType
  2348.  
  2349. Typed files are essentially unlimited sequences of elements of
  2350. that one element type.  The Write command can be used to write
  2351. individual elements to the end of the file, and the Read command
  2352. can be used to input the current element and move the file pointer
  2353. to the next one.  You can only write one type of element to each
  2354. typed file.
  2355.  
  2356. Typed files store their elements in exactly the same format that
  2357. they appear in memory, so they are often unreadable.  A file of
  2358. character elements is readable, but a file of integer elements
  2359. would be incomprehensible.  Since typed files always store
  2360. complete elements, each element is necessarily a fixed size.
  2361.  
  2362. You don't actually need anything but typed files - anything you
  2363. can do with Pascal files can be done with them.  For the sake of
  2364. convenience, however, Pascal also uses the Text file type.  The
  2365. Text file is a special kind of "File of Char", but is not
  2366. compatible with it.  Text files are made up of ASCII characters
  2367. broken up into variable length lines.  Each line is terminated by
  2368. a special newline character, which on the Amiga is the line feed
  2369. character (ASCII 10.  On MS-DOS machines, the newline character is
  2370. the carriage return/line feed sequence).
  2371.  
  2372. Since Text files (like this documentation, and all the source
  2373. files) are so common, Pascal has a variety of routines built-in to
  2374. read and write values to and from them.  Most of the standard
  2375. types, for example, have a special routine for converting them
  2376. into ASCII characters and writing them to a file.  These routines
  2377. are called automatically by the compiler to write each expression
  2378. in a Write procedure to a Text file.  Similar routines exist for
  2379. reading the same types.  The descriptions of the Read and Write
  2380. procedures below described exactly how this conversion takes
  2381. place.
  2382.  
  2383. There is even a special form of the Read and Write procedures
  2384. designed to work only with Text files - the ReadLn and WriteLn
  2385. commands.  They are explained below, but note that since typed
  2386. files have no lines, these two routines are used only for Text
  2387. files.
  2388.  
  2389.  
  2390.  Opening Files
  2391. ---------------
  2392.  
  2393. There are several closely related routines for opening Pascal
  2394. files.  For opening input files, which are existing files that
  2395. will be opened for reading, you can use either the ReOpen()
  2396. function or the Reset() procedure.  They are defined as follows:
  2397.  
  2398.  
  2399.  
  2400.                Reset(var FileVar : File or Text;
  2401.                         FileName : String;
  2402.                       BufferSize : Integer);
  2403.  
  2404. The "Reset" procedure opens a file for reading.  The FileVar
  2405. parameter specifies the Pascal file variable that should be
  2406. associated with this AmigaDOS file.  The FileName is the file
  2407. name, with a complete path if necessary.  Since this can be any
  2408. valid AmigaDOS filename, it can actually refer to the printer, a
  2409. console window, or all sorts of other things.
  2410.  
  2411. The BufferSize parameter specifies the size of the buffer you
  2412. want, in bytes.  When PCQ tries to open your file, it will try to
  2413. allocate this much memory as a buffer.  If it can't, it sets
  2414. IOResult and fails.  Actually, PCQ tries to allocate a buffer that
  2415. is an even multiple of the file element size, not larger than
  2416. BufferSize, but at least one element long (the element size for
  2417. Text files is one character).  The BufferSize parameter is
  2418. entirely optional - if it's not included, a default value of 128
  2419. is used.
  2420.  
  2421. If you are using automatic IO checking, your program will abort
  2422. with a runtime error if the file cannot be opened.  If you are
  2423. checking manually, it will just set IOResult.
  2424.  
  2425. The variable FileVar should not refer to an file that's already
  2426. open.  Either the file should be closed first, or you should use a
  2427. different file variable.
  2428.  
  2429.  
  2430.  
  2431.              ReOpen(fname      : String;
  2432.                     var fvar   : file or text;
  2433.                     buffersize : Integer) : Boolean
  2434.  
  2435. ReOpen is the function form of Reset.  It attempts to open a file
  2436. in the same way as Reset, and if everything goes O.K. it returns
  2437. True.  If there was a problem, it returns False.
  2438.  
  2439. ReOpen never sets IOResult, so if you are using automatic IO
  2440. checking a call to ReOpen will not abort the program.  As in the
  2441. Reset procedure, the BufferSize parameter is optional.
  2442.  
  2443.  
  2444.  
  2445. If you need to open a file for writing (which deletes any existing
  2446. file of the same name!), you can use the Rewrite procedure or the
  2447. Open() function.  They are defined as:
  2448.  
  2449.  
  2450.  
  2451.              Rewrite(var FileVar : File or Text;
  2452.                         FileName : String;
  2453.                       BufferSize : Integer);
  2454.  
  2455. Rewrite opens an AmigaDOS file for writing, erasing any existing
  2456. file with the same name.  The parameters are just like the Reset
  2457. command, and the BufferSize is still optional.
  2458.  
  2459. Rewrite sets IOResult, so if your program is using automatic IO
  2460. checking it will abort if the file cannot be opened.  Programs
  2461. handling their own IO checks should be sure to look at IOResult.
  2462.  
  2463. As with all the file opening routines, you should not use a file
  2464. variable that already refers to an open file.
  2465.  
  2466.  
  2467.  
  2468.                Open(fname      : String;
  2469.                     var fvar   : file or text;
  2470.                     buffersize : Integer) : Boolean
  2471.  
  2472. Open is equivalent to Rewrite, but in function form.  It attempts
  2473. to open the file for writing, and if everything goes O.K.  it
  2474. returns True.  If there is any problem, it returns false.
  2475. Remember that opening a file for output means that any existing
  2476. file with the same name gets erased.
  2477.  
  2478. Open does not set IOResult, so programs using automatic IO
  2479. checking can use it without aborting.  The BufferSize parameter,
  2480. just as in the rest of the file opening routines, is optional.
  2481.  
  2482.  
  2483.  
  2484.  Writing to Files
  2485. ------------------
  2486.  
  2487. Output in Pascal is handled by the Write and Writeln procedures.
  2488. Unlike most Pascal procedures, these routines will accept an
  2489. unlimited number of parameters.  If you are writing to a Text
  2490. file, the parameters can be a variety of types.  The Write
  2491. procedure has the following basic form:
  2492.  
  2493.  
  2494.      Write(var FileVar : Text or Typed File, Expressions...)
  2495.  
  2496. The FileVar is optional.  If it is not included, the standard Text
  2497. file Output is used in its place.  If the FileVar is a typed file,
  2498. each expression must be of the element type.  They will be written
  2499. to the file with no space in between them, formatted just as they
  2500. are in memory.
  2501.  
  2502. If you are writing to a text file, it's a different story
  2503. entirely.  First of all, each expression can take the form "e:m:n"
  2504. where e is the expression itself and m and n are constant
  2505. integers.  m specifies the minimum field width - if the item to be
  2506. written would take up fewer than m characters, spaces are written
  2507. to fill out the field.  n is only allowed if e is an expression of
  2508. type Real, and it specifies how many digits to the right of the
  2509. decimal point will be written out.  The default values for m and n
  2510. are 1 and 2, respectively.  Specifically what gets written out
  2511. depends on the type, according to the following:
  2512.  
  2513. Integer
  2514. Word
  2515. Short
  2516. Byte     These four types are all written as sequences of ASCII
  2517.          digits, as expected.  They are not preceded by any spaces,
  2518.          but Short and Integer types might lead off with a minus
  2519.          sign if appropriate.  There will be no trailing spaces.
  2520.  
  2521. Real     The entire integer part (the part to the left of the
  2522.          decimal point) is written out.  If n is not zero, a
  2523.          decimal point followed by n fractional digits are written
  2524.          out.  Note that for Real numbers, m indicates the number
  2525.          of digits to the left of the decimal point that should be
  2526.          written, not the full field width (this will probably
  2527.          change in the next version).
  2528.  
  2529. Char     A character is written out as just the single character,
  2530.          unchanged.
  2531.  
  2532. Array of Char
  2533.          The entire array, for its whole declared length, is
  2534.          written out character by character.
  2535.  
  2536. String   The entire string up to, but not including, the
  2537.          terminating null character is written.
  2538.  
  2539. Boolean  Either the word TRUE or the word FALSE is written, with
  2540.          no leading or trailing spaces.
  2541.  
  2542.  
  2543.  
  2544.            WriteLn(var FileVar : Text; Expressions...)
  2545.  
  2546. Writeln is exactly the same as Write, but after is has written out
  2547. each of the expressions according to the rules above, it also
  2548. writes out a newline character.  WriteLn can only be used on Text
  2549. files.
  2550.  
  2551.  
  2552.  Reading from Files
  2553. --------------------
  2554.  
  2555. Input in Pascal is handled by the Read procedure.  Like the Write
  2556. procedures, Read accepts any number of parameters, and many types
  2557. of parameters if you are reading from a Text file.  The format is
  2558. as follows:
  2559.  
  2560.    Read(var FVar : Text or Typed File; Variable References....)
  2561.  
  2562. The FVar parameter is optional.  If it is omitted, the standard
  2563. Text file "Input" is used in its place.
  2564.  
  2565. If FVar refers to a typed file, each variable reference is filled
  2566. with the subsequent file elements, unless EOF is reached or some
  2567. other error occurs first.  Reading from a Text file is a somewhat
  2568. more flexible job.  Just as with the Write statements, what
  2569. happens depends on the type being read, according to the
  2570. following:
  2571.  
  2572. Integer
  2573. Word
  2574. Short
  2575. Byte     All white space, which is defined as any character whose
  2576.          ASCII value is less than or equal to 32 (the space
  2577.          character) is skipped.  If the first non-white space
  2578.          character is not a digit or the EOF is reached, an IO
  2579.          error is raised (see Exit Procedures for more
  2580.          information).  If not, digits are read until the first
  2581.          non-digit.  The resulting number is returned, and the
  2582.          file pointer rests on that non-digit.
  2583.  
  2584. Real     First, an integer is read exactly as above.  If the next
  2585.          character is a period, digits are again read in as
  2586.          fractional digits until the first non-digit.  The pointer
  2587.          rests on that first non-digit.  A Real value does not
  2588.          need a fractional part, nor does it require a decimal 
  2589.          point.
  2590.  
  2591. Char     Reads the next single character.  Standard Pascal
  2592.          translates end-of-line characters into spaces, but PCQ
  2593.          Pascal, like Turbo Pascal, allows them to come through as
  2594.          ASCII linefeeds.
  2595.  
  2596. Array of Char
  2597.          Reads characters into the array until either the array is
  2598.          full, or the end-of-line is reached.  If the end-of-line
  2599.          is reached, the rest of the array is padded with spaces
  2600.          and the file pointer is left pointing at the end-of-line
  2601.          character - you'll need to call Readln to get rid of it.
  2602.  
  2603. String   Reads characters into the String buffer until the
  2604.          end-of-line is reached.  At that point the string is
  2605.          terminated by a zero byte, and the file pointer is left
  2606.          pointing to the end-of-line character.  Note that this
  2607.          routine does not check for length, so you need to be sure
  2608.          to provide a large enough string for the file you are
  2609.          reading.
  2610.  
  2611. Boolean  Can't be done.
  2612.  
  2613.  
  2614. A series of variable references in a Read procedure acts exactly
  2615. like each of the references in individual Read procedures.  Thus:
  2616.  
  2617.                      Read(Input, Var1, Var2);
  2618.  
  2619. is equivalent to:
  2620.  
  2621.               Read(Input, Var1); Read(Input, Var2);
  2622.  
  2623. which is also equivalent to:
  2624.  
  2625.                      Read(Var1); Read(Var2);
  2626.  
  2627.  
  2628.  
  2629.          ReadLn(var FVar : Text; Variable References...)
  2630.  
  2631. Readln is exactly like Read, but after all the specified variables
  2632. have been read, this command eats characters until it finds the
  2633. next end-of-line, and it eats that too.  This command can only be
  2634. used on Text files.
  2635.  
  2636.  
  2637.  File Buffers
  2638. --------------
  2639.  
  2640. Like Standard Pascal, but unlike Turbo Pascal, PCQ allows you to
  2641. access the file buffer directly.  The syntax of the reference
  2642. looks like:
  2643.  
  2644.                    <File Variable Reference> ^
  2645.                           e.g. FileVar^
  2646.  
  2647. That expression has the same type as the elements of the file
  2648. itself (Text files have Char elements).  With input files, this
  2649. syntax looks at the next element that will be input by the Read()
  2650. procedure, like a look-ahead.  If EOF(FileVar) is True, then
  2651. FileVar^ is invalid.
  2652.  
  2653. For output files, the file buffer reference shows you the output
  2654. buffer.  This is not the value that will be written out with the
  2655. Write() procedure - see the description of Put() below for more
  2656. information.
  2657.  
  2658. Logically, the file buffer you access through this syntax is only
  2659. as long as one element, but the actual buffer in memory can be of
  2660. virtually any size.  See the file opening commands for information
  2661. on setting the buffer size.
  2662.  
  2663. Using this syntax in PCQ is actually considered an IO operation,
  2664. in the sense that it can set IOResult.  This only occurs when the
  2665. file is interactive, because the buffers of interactive files are
  2666. not kept full.
  2667.  
  2668. If you are making use of the file buffer, you will probably use on
  2669. or both of the following routines:
  2670.  
  2671.  
  2672.               Get(var FileVar : Text or Typed File)
  2673.  
  2674. Get just moves the file pointer from the current element to the
  2675. next one.  That may involve calling DOS to refill the buffer, but
  2676. normally it's just a matter of adjusting a field in the file
  2677. variable itself.  It is an error to call this routine on a file
  2678. for which EOF(FileVar) is True.
  2679.  
  2680. Every read from a typed file of the form "Read(FVar,Element)" can
  2681. be thought of as:
  2682.  
  2683.         Element := FVar^; { To assign the current value }
  2684.         Get(FVar);        { To advance the file pointer }
  2685.  
  2686.  
  2687.               Put(var FileVar : Text or Typed File)
  2688.  
  2689. Put moves the file pointer past the current element in an output
  2690. file, writing the buffer to disk if necessary.  Every statement of
  2691. the form "Write(FVar,Expr)", where FVar is a typed file, could be
  2692. implemented as:
  2693.  
  2694.         FVar^ := Expr; { Set the buffer value }
  2695.         Put(FVar);     { Commit the buffer    }
  2696.  
  2697. Note that until the Put procedure is called, any assignments to
  2698. the file buffer will write over each other.
  2699.  
  2700.  
  2701.  IO Checking
  2702. -------------
  2703.  
  2704. Input & Output can cause more unforeseen errors than virtually any
  2705. other area of programming.  PCQ Pascal catches IO errors in one of
  2706. two ways.  The first is called automatic IO checking - PCQ checks
  2707. for errors after each and every IO operation.  If there is an
  2708. error, the program aborts with a runtime error.  Believe it or
  2709. not, that's the default behavior.
  2710.  
  2711. If you turn off automatic checking using the {$I-} compiler
  2712. directive, you become responsible for checking for errors.  You do
  2713. this by calling the IOResult function, which returns 0 if
  2714. everything is O.K., or some other number if there was a problem.
  2715. When you call IOResult, you automatically clear its value, so if
  2716. you are going to use the error code later on you need to save it
  2717. in a variable.
  2718.  
  2719. IOResult is set by every IO routine.  No IO routines will function
  2720. if IOResult is not zero, so you should check for errors whenever
  2721. possible to avoid skipping reads and writes.
  2722.  
  2723. The values returned by IOResult are the same as the runtime
  2724. errors - possible values are listed in the section called Exit
  2725. Procedures.
  2726.  
  2727.  
  2728.  Standard IO
  2729. -------------
  2730.  
  2731. One of the tricky parts of programming on the Amiga is that a
  2732. program can be launched from two very different environments.  The
  2733. CLI invokes a program in much the same way as MS-DOS does - the
  2734. program has obvious input and output channels.  The Workbench, on
  2735. the other hand, offers nothing of the sort.  A program that needs
  2736. input and output channels must establish them explicitly.
  2737.  
  2738. All PCQ Programs establish some sort of standard input and output
  2739. channels, which are accessed through the Text files Input and
  2740. Output.  What those files represent depends, naturally, on the
  2741. environment from which the program was executed.
  2742.  
  2743. Let's take the simple case first.  If you run a program from the
  2744. CLI, Input and Output will refer to the CLI window itself.  Unless
  2745. you use indirection, that is, in which case Input and Output will
  2746. refer to the channels specified on the command line (see an
  2747. AmigaDOS manual for more information).  Maybe that wasn't so
  2748. simple after all.
  2749.  
  2750. If the program was launched from the Workbench, the startup code
  2751. goes through several steps to establish Input and Output.  First
  2752. of all, it looks at the value of the standard String typed
  2753. constant StdInName.  If StdInName is Nil, no file is opened and
  2754. referring to Input will cause grave problems.  If not, the startup
  2755. code attempts to open the file.  If it can't do it, it terminates
  2756. with run-time error 53.  If all went well, Input is established.
  2757.  
  2758. Next the startup code looks at StdOutName.  If it's Nil, Output is
  2759. not established, so any Write procedures had better use an
  2760. explicit file.  If StdOutName refers to the same string as
  2761. StdInName (not two strings with the same contents - it actually
  2762. has to point to the same memory), and if the file associated with
  2763. Input is interactive (i.e.  attached to a console window), then
  2764. Output is associated with the same file handle as Input.  The
  2765. default values of StdInName and StdOutName have this property.  If
  2766. either of those tests fail, the startup code tries to open a file
  2767. according to StdOutName, and if it works, then Output is set up
  2768. accordingly.  Otherwise, the program will terminate with runtime
  2769. error 57.
  2770.  
  2771. The default values for the two channels are defined in PCQ.lib as
  2772. follows:
  2773.  
  2774.         CONST
  2775.             StdInName  : String = "CON:0/0/640/200/";
  2776.             StdOutName : String = StdInName;
  2777.  
  2778. According to the rules specified above, this would normally result
  2779. in one full-screen console window being opened, with input coming
  2780. from it and output going to it.
  2781.  
  2782. Note that StdInName and StdOutName are defined as typed constants.
  2783. They can't be variables, because they are opened before any of
  2784. your code executes.  If that's a major problem, you can define
  2785. them both as Nil, and from inside your program you can open Input
  2786. and Output as anything you like.  You should probably re-use Input
  2787. and Output only when your program was run from the Workbench (you
  2788. can check if you were run from the Workbench by calling
  2789. GetStartupMsg from "Utils/Parameters.i").
  2790.  
  2791. If you compiled your program using the "-s" small initialization
  2792. code switch, all bets are off:  Input and Output are not
  2793. established, and in fact none of the other IO routines are
  2794. initialized either.  See the section called Small Initialization
  2795. Code for more information.
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801. ===================================================================
  2802.  
  2803.                            Strings
  2804.  
  2805. ===================================================================
  2806.  
  2807. PCQ Pascal strings are similar to C strings, and nothing at all
  2808. like Turbo Pascal strings.  That's too bad, because Turbo Pascal
  2809. strings are a lot easier to work with.  Eventually, PCQ Pascal
  2810. strings will be the same as Turbo Pascal strings, but that day has
  2811. yet to come.
  2812.  
  2813. The string type can be thought of as simply "^Char".  Thus all
  2814. string variables take up exactly 4 bytes, and they store the
  2815. address of the actual text.  The text can be of any length, and
  2816. is terminated by the character Chr(0).  A statement like:
  2817.  
  2818.         StringVar := "A String"
  2819.  
  2820. ... actually stores the address of the constant string in the
  2821. string variable, rather than copying the string itself into some
  2822. existing space.
  2823.  
  2824. String constants in the Pascal text are delimited by double quote
  2825. characters, as opposed to the single quote characters of character
  2826. array constants.  Thus "A String" is considered a constant of type
  2827. String, whereas 'not a string' is considered a constant of type
  2828. "Array [0..11] of Char".
  2829.  
  2830. Strings are defined as simple pointers, so the reference
  2831. "StringVar^" is valid, and is of type Char.  It actually points to
  2832. the first byte within the string buffer.  But unlike normal
  2833. pointers, the individual characters in a string can also be
  2834. accessed through subscript notation.  For example, to get the
  2835. fourth character in a string, you could use "StringVar[3]".
  2836. Remember that "StringVar[0]" is the first element.
  2837.  
  2838.  
  2839.  Allocating String Space
  2840. -------------------------
  2841.  
  2842. Since the actual String variables only store an address, you need
  2843. to allocate some space for the actual text.  C allows you define
  2844. that space when you declare the string type, but PCQ Pascal
  2845. doesn't even offer that much.  In PCQ Pascal, you have to
  2846. explicitly allocate the memory from the system, or assign the
  2847. address of a buffer variable to the string.  There are several
  2848. functions, all defined in the include file StringLib.i, that
  2849. allocate space for strings.  They are:
  2850.  
  2851.                AllocString(Size : Integer) : String
  2852.  
  2853. AllocString simply returns an uninitialized memory area that is at
  2854. least Size bytes long.  This memory is considered PCQ memory, so
  2855. it is returned to the system after its use (see the section called
  2856. Memory Management for more information).
  2857.  
  2858.                 strdup(InString : String) : String
  2859.  
  2860. The strdup (string duplicate) function is equivalent to the
  2861. following:
  2862.                 temp := AllocString(strlen(InString));
  2863.                 strcpy(temp,InString);
  2864.                 strdup := temp;
  2865.  
  2866. In other words, it allocates just enough memory to hold the input
  2867. string, then makes a copy of the input string in the new buffer.
  2868. This memory is also considered PCQ memory, so it will be returned
  2869. to the system when the program terminates.
  2870.  
  2871. The other way to set up a string buffer is to assign the string
  2872. variable the address of an array declared elsewhere.  Thus the
  2873. following:
  2874.  
  2875.         Var
  2876.             String1 : String;
  2877.             Buffer1 : Array [0..127] of Char;
  2878.         begin
  2879.             String1 := Adr(Buffer1);
  2880.  
  2881. ... sets up a 128-character buffer for String1.  If you try to
  2882. store a 129-character string in that buffer, all sorts of problems
  2883. will result, so take care.
  2884.  
  2885.  
  2886.  Using Escape Characters
  2887. -------------------------
  2888.  
  2889. There are, of course, lots of useful characters that can't easily
  2890. be written into a program source file.  The end-of-line character,
  2891. for example, is always considered the end of a line, rather than
  2892. taken as a constant.  If you need to include this sort of
  2893. character in any text constant (a Char, Array of Char, or String),
  2894. you use the C escape convention, in which a backslash "\" is
  2895. followed by a special character.  The escape sequences supported
  2896. by PCQ are:
  2897.  
  2898.            \n   Line Feed, chr(10)
  2899.            \t   Tab, chr(9)
  2900.            \0   Null, chr(0)
  2901.            \b   Backspace, chr(8)
  2902.            \e   ESC, chr(27)
  2903.            \c   CSI (Control Sequence Introducer), chr($9B)
  2904.            \a   Attention, chr(7)
  2905.            \f   Form Feed, chr(12)
  2906.            \r   Carriage Return, chr(13)
  2907.            \v   Vertical Tab, chr(11)
  2908.  
  2909. Every other character passes through unchanged, so the following
  2910. definitions also hold:
  2911.  
  2912.            \\   Just a single backslash
  2913.            \'   A single quote, even in a single-quote-delimited
  2914.                 constant
  2915.            \"   A double quote, even in a String constant
  2916.  
  2917. Thus a string like "A\tboy\nand\\his \"dog." becomes:
  2918.  
  2919.         |A      boy
  2920.         |and\his "dog
  2921.  
  2922. ... where the vertical bar | represents the left margin.
  2923.  
  2924.  
  2925.  StringLib
  2926. -----------
  2927.  
  2928. StringLib.i is an include file in the Utils directory that defines
  2929. a bunch of C-style functions for use on strings.  Those functions
  2930. are explained in the include file itself.  The source for these
  2931. routines is in the runtime library source, which is available by
  2932. request.
  2933.  
  2934.  
  2935.  
  2936.  
  2937. ===================================================================
  2938.  
  2939.                         Memory Management
  2940.  
  2941. ===================================================================
  2942.  
  2943. One of the problems with Amiga programming is that there is no
  2944. resource tracking.  In an MS-DOS program, you can open files and
  2945. allocate memory like crazy, then just quit the program and
  2946. everything's O.K.  On the Amiga, all those files would stay open
  2947. and the memory would stay allocated.  You are expected to clean up
  2948. after yourself.
  2949.  
  2950. To help you do that, PCQ Pascal uses a special memory allocation
  2951. scheme that uses the Intuition AllocRemember routine to keep track
  2952. of all your memory allocations.  When your program terminates, any
  2953. memory you haven't deallocated is automatically freed by an exit
  2954. procedure.
  2955.  
  2956. This only works for memory allocated through one of the special
  2957. PCQ routines New, AllocString (from Utils/StringLib.i) or GetMem
  2958. (from Utils/PCQMemory.i).  Memory allocated through one of these
  2959. routines is called PCQ memory, but of course it's no different
  2960. from normal system memory except that it will be returned.
  2961.  
  2962. Even though it will be automatically freed, you should deallocate
  2963. memory as soon as you are through with it.  There might be other
  2964. programs running that can use it.  If you do free PCQ memory, you
  2965. need to use Dispose, FreeString or FreePCQMem to do it.  If you
  2966. don't, the memory will be returned to the system, but the PCQ
  2967. memory routines won't know about it.  They will, therefore, try to
  2968. free it again when the program terminates.  Guru.
  2969.  
  2970. PCQ memory is always allocated with the flags MEMF_PUBLIC and
  2971. MEMF_CLEAR.  If you need chip memory, therefore, you should use
  2972. the normal Exec function AllocMem (from Exec/Memory.i).
  2973.  
  2974.  
  2975.  HeapError
  2976. -----------
  2977.  
  2978. So what happens when the PCQ memory routines are unable to
  2979. allocate some memory a user has called for?  That depends on the
  2980. value of HeapError, a standard Address variable.  HeapError
  2981. contains the address of a function that has a header with the
  2982. following form:
  2983.  
  2984.            Function HeapFunc(Size : Integer) : Integer;
  2985.  
  2986. The Size parameter is the amount of memory the allocator was
  2987. trying to get, and the integer returned determines how the
  2988. allocator will respond to the problem.  If it returns 0, the
  2989. allocator will abort the program with runtime error 54 (this is
  2990. the default).  If it returns 1, the allocator will return the
  2991. value Nil, so you'll have to check after each call to New,
  2992. AllocString or GetMem for a Nil value.  If the HeapError function
  2993. returns 2, the allocator tries the allocation again.  This gives
  2994. you a chance to free up some memory, if possible.  If that
  2995. allocation fails, the HeapError function will get called again.
  2996.  
  2997. To install a function as the HeapError function, you would use
  2998. something like the following:
  2999.  
  3000.                      HeapError := @HeapFunc;
  3001.  
  3002. ... where HeapFunc is defined as above.
  3003.  
  3004.  
  3005.  
  3006.  
  3007. ===================================================================
  3008.  
  3009.                          Exit Procedures
  3010.  
  3011. ===================================================================
  3012.  
  3013. Exit procedures are routines that you set up to run after the main
  3014. routine is finished, or if there is a run-time error.  They are
  3015. used to return resources to the system, or to exit gracefully or
  3016. even recover from run-time errors.
  3017.  
  3018. How it works is:  when a program terminates, for whatever reason,
  3019. PCQ examines the value of ExitProc, a standard Address variable.
  3020. If it is non-Nil, PCQ sets ExitProc to Nil and calls the procedure
  3021. it pointed to.  When the procedure returns, PCQ checks ExitProc
  3022. again, and continues calling exit procedures until ExitProc is
  3023. Nil.  The normal PCQ initialization code sets up an exit procedure
  3024. that frees all memory allocated through New or AllocString, and
  3025. closes any Pascal files that remain open.  Normal programs,
  3026. therefore, have at least one exit procedure.
  3027.  
  3028. To make a procedure an exit procedure, first define a routine with
  3029. no parameters.  Then you set the ExitProc standard variable to the
  3030. address of your routine.  In most cases you'll want to save the
  3031. previous value of ExitProc so all the other exit procedures can
  3032. run as well.  Within the exit procedure itself, you should reset
  3033. ExitProc to point to the previous routine.
  3034.  
  3035. There are two additional variables associated with exit procedures
  3036. that are only valid while the procedure is actually running as an
  3037. exit procedure.  They always exist, but their value is only set
  3038. when the program terminates.  They are:
  3039.  
  3040. ExitCode     ExitCode contains the value of any runtime error that
  3041.              caused the program termination.  This is either a
  3042.              value you supplied through the Exit() routine, or a
  3043.              runtime error code.
  3044.  
  3045. ExitAddr     ExitAddr is the address where a runtime error
  3046.              occurred.  It is only valid when ExitCode is non-zero.
  3047.              It can (in theory) be used to recover from a runtime
  3048.              error, but you'd have to be awfully familiar with the
  3049.              actual runtime code to get it to work.  Of course you
  3050.              can get the runtime source from me.
  3051.  
  3052.  
  3053.  Runtime Errors
  3054. ----------------
  3055.  
  3056. There are several errors that will cause a PCQ program to
  3057. immediately terminate.  When that happens, ExitCode will be set to
  3058. a specific value, which will eventually be returned to AmigaDOS.
  3059. AmigaDOS, in turn, will normally ignore it, so you'll never see
  3060. it.  The two ways I know of the see the return value (if it is
  3061. non-zero) are to run the program in a script, or to run the
  3062. program using AmigaDOS's Run command.  In either case, if the
  3063. program has a non-zero return code AmigaDOS will write out
  3064. "ProgramName failed returncode #".
  3065.  
  3066. The runtime errors generated by PCQ programs are as follows:
  3067.  
  3068.  
  3069.             Code       Description
  3070.           ----------------------------------------------
  3071.              50    No memory for IO buffer (1)
  3072.              51    Read past EOF (1)
  3073.              52    Input file not open (2)
  3074.              53    Could not open StdInName (3)
  3075.              54    New() failed (4)
  3076.              55    Integer divide by zero
  3077.              56    Output file not open (2)
  3078.              57    Could not open StdOutName (3)
  3079.              58    Found EOF before first digit while
  3080.                    reading an integer (1)
  3081.              59    No digits found in reading an integer (1)
  3082.              60    Range error (5)
  3083.              61    Could not open required library
  3084.  
  3085.         The following AmigaDOS error codes can result from a call
  3086.         to Open, ReOpen, Write, Read, etc:  (1)
  3087.  
  3088.             103    Insufficient free store
  3089.             202    Object in use
  3090.             203    Object already exists
  3091.             204    Directory not found
  3092.             205    Object not found
  3093.             206    Invalid window specification
  3094.             210    Invalid component name
  3095.             212    Object wrong type
  3096.             213    Disk not validated
  3097.             214    Disk write protected
  3098.             218    Device not mounted
  3099.             221    Disk full
  3100.             223    File is write protected
  3101.             224    File is read protected
  3102.             225    Not a DOS disk
  3103.             226    No disk in drive
  3104.  
  3105.         (1)  These errors only cause runtime errors when automatic
  3106.              IO error checking is enabled (it's the default).  If
  3107.              you have used the {$I-} directive to indicate that
  3108.              you'll check IOResult explicitly, the program will
  3109.              not automatically terminate.
  3110.         (2)  PCQ cannot always determine when the file is not
  3111.              open.  If it can, it issues this error.  If it can't,
  3112.              the machine will crash.
  3113.         (3)  These errors occur in the initialization code, before
  3114.              any exit procedures are established.
  3115.         (4)  See the section called Memory Management to see how
  3116.              keep a runtime error from being issued.
  3117.         (5)  This only occurs if you have turned range checking on
  3118.              with the {$R+} directive.
  3119.  
  3120.  
  3121.  
  3122.  
  3123.  
  3124. ===================================================================
  3125.  
  3126.                        Compiler Directives
  3127.  
  3128. ===================================================================
  3129.  
  3130. There are several options that PCQ Pascal provides that are not
  3131. useful for all programs.  For example, a large application should
  3132. not terminate with a runtime error if it can't open a file.
  3133. Therefore PCQ Pascal allows you to determine several aspects of
  3134. the program generated from your code.
  3135.  
  3136. You control these options by issuing compiler directives.
  3137. Compiler directives are contained in comments, and must begin with
  3138. a dollar sign "$" as the first character in the comment.
  3139. Immediately following the dollar sign is a letter indicating the
  3140. directive, which is then followed by zero or more characters
  3141. giving additional information.
  3142.  
  3143. You can include more than one directive in a single comment by
  3144. separating the directives by commas.  Thus the following
  3145. directives turn IO checking off, and range checking on:
  3146.  
  3147.                              {$I-,R+}
  3148.  
  3149. The following directives are supported:
  3150.  
  3151.              {$A Any number of assembly instructions}
  3152.  
  3153. The $A directive allows you to insert assembly language
  3154. instructions into the source code at the given point.  The text of
  3155. the instructions is passed through to the assembler unchanged, so
  3156. you should include comments and make variable references according
  3157. to assembly language style.
  3158.  
  3159. Since comments are allowed anywhere that white space is allowed,
  3160. you could technically insert some assembly language instructions
  3161. in the middle of an expression.  That could produce unpredictable
  3162. results, however, so you should use assembly language only between
  3163. statements.
  3164.  
  3165.                           {$B+} or {$B-}
  3166.  
  3167. The $B directive turns short-circuit evaluations on and off.  If
  3168. you use the $B+ directive to turn short-circuit evaluations on,
  3169. which is actually the default, PCQ will evaluate Boolean
  3170. expressions normally, but as soon as the final value of the
  3171. expression is known, it will skip any remaining parts of the
  3172. expression.  Thus in a series of "and" clauses, as soon as one of
  3173. them evaluates to False, the rest are not evaluated at all.  In a
  3174. series of "or" clauses, as soon as one of them evaluates to True,
  3175. the rest are skipped.  If you are using short-circuit evaluations
  3176. the expression will always be evaluated from left to right.
  3177. Short-circuits make Boolean evaluation somewhat faster, especially
  3178. in long equations.
  3179.  
  3180. If you turn short-circuit evaluations off using the $B- directive,
  3181. all parts of a Boolean expression will be evaluated even if the
  3182. outcome is not in doubt, and the expression will not necessarily
  3183. be evaluated in left-to-right order.
  3184.  
  3185.                           {$C+} or {$C-}
  3186.  
  3187. The $C directive controls whether PCQ uses the normal or C style
  3188. procedure calling format.  In the default state, {$C-}, PCQ pushes
  3189. procedure and function arguments on the stack from left to right.
  3190. In the {$C+} state, the arguments are pushed on the stack from
  3191. right to left.  This makes it easier to use C language object
  3192. libraries, and also let's you use variable numbers of parameters.
  3193.  
  3194.                            {$I "fname"}
  3195.  
  3196. This directive inserts the file "fname" into the input stream at
  3197. the current position in the file.  When the included file has been
  3198. fully read, the input is again taken from the original file.  You
  3199. can't use any other directives after this one, but you can include
  3200. any comments you like after the file name.
  3201.  
  3202. In order to keep from including a file more than once, the
  3203. compiler keeps a list of all file name already included.  If the
  3204. file name matches one already on the list, it is not included.
  3205. Note that only the actual file name, not the entire path, is
  3206. compared.  Thus you should be sure that all your include files
  3207. have unique names.
  3208.  
  3209. Almost all the example programs demonstrate the use of include
  3210. files.
  3211.  
  3212.                           {$I+} or {$I-}
  3213.  
  3214. The other form of the $I directive determines your programs
  3215. reaction to Input/Output errors.  The default behavior, which
  3216. corresponds to the {$I+} directive, is to issue a runtime error
  3217. whenever an error is detected in an IO routine.  The other option,
  3218. specified by the {$I-} directive, indicates that the program
  3219. itself will check the IOResult function after IO operations, and
  3220. handle any errors accordingly.  See the Input/Output section for
  3221. more information.
  3222.  
  3223.                           {$N+} or {$N-}
  3224.  
  3225. This directive determines which routines are used to implement the
  3226. standard functions sin, cos, exp, etc.  In the {$N-} case, which
  3227. is the default, the compiler uses its own routines.  In the {$N+}
  3228. case, the compiler calls the Amiga's mathtrans.library for these
  3229. functions.  The MathTrans routines are faster and more accurate
  3230. than PCQ's private routines, but they require that the user have
  3231. the correct library in the LIBS: directory.
  3232.  
  3233.                           {$O+} or {$O-}
  3234.  
  3235. These options are identical to the {$I+} and {$I-} options.
  3236.  
  3237.                           {$R+} or {$R-}
  3238.  
  3239. The $R directive determines whether the compiler will verify that
  3240. index values are within the specified range of the array.  The
  3241. default behavior is {$R-}, which means that the compiler will not
  3242. generate the extra code.  Specifying {$R+} makes the compiler
  3243. issue a runtime error with error code 60.  Turning this option on
  3244. results in larger and slower programs, so I would recommend only
  3245. using the option while testing.
  3246.  
  3247.                  {$SN} or {$SX} or {$SP} or {$SD}
  3248.  
  3249. The $S option controls the storage of global variables and typed
  3250. constants.  The N option (for Normal storage) tells the compiler
  3251. that for all subsequent global variables, the compiler should
  3252. allocate memory in the data segment, and also issue an external
  3253. definition (XDEF in assembly language) for the identifier, so it
  3254. can be used by external routines.  This is the normal storage
  3255. scheme for PCQ programs.
  3256.  
  3257. The X option (for eXternal storage) tells the compiler that all
  3258. subsequent global variables are defined outside of the program.
  3259. Therefore the compiler should not allocate any space for the
  3260. variables, but simply create an external reference (XREF in
  3261. assembly language).  This is the normal storage scheme for
  3262. external files.
  3263.  
  3264. The P option (for Private storage) tells the compiler that it
  3265. should allocate space for global variables, but it should not
  3266. export the identifier itself.  This allows external files to have
  3267. global variables that do not affect the main program.
  3268.  
  3269. The D option (for Default storage) resets the storage to its
  3270. standard value.  In an external program, it acts like {$SX}, and
  3271. in a normal program it acts like {$SN}.
  3272.  
  3273.                           {$X+} or {$X-}
  3274.  
  3275. In the default $X- state, you can only call functions from within
  3276. expressions.  If you use the $X+ directive, however, you can call
  3277. functions as if they were procedures, ignoring the values
  3278. returned.
  3279.  
  3280.  
  3281. ===================================================================
  3282.  
  3283.                             Type Casts
  3284.  
  3285. ===================================================================
  3286.  
  3287. If you are using a strongly typed language like Pascal, you need a
  3288. way to get around the type rules.  PCQ Pascal uses the same method
  3289. as Turbo Pascal and Modula-2 to get around the type checks.  The
  3290. format for a type cast is as follows:
  3291.  
  3292.         <Type ID> ( <Expression or Variable Reference> )
  3293.  
  3294. This looks just like a function, but it is definitely not one.  A
  3295. type cast never generates any code - it just lets the code get by
  3296. the compiler.  Naturally, this can lead to some serious problems.
  3297. For example, a type cast like "Short(EnumeratedVar)" will cause
  3298. problems because enumerated types are normally one byte long.  You
  3299. have told the compiler to consider it a two byte value, but the
  3300. other byte is undefined.  The correct way to handle that call
  3301. would be to use the Ord() function, or at least cast it to a Byte
  3302. instead.
  3303.  
  3304. The difference between Short() and Ord() in this example is that
  3305. Ord() is a type transfer function, whereas Short() is not a
  3306. function at all.  As another example, consider the fragment below:
  3307.  
  3308.         Writeln(Integer(2.0));
  3309.         Writeln(Trunc(2.0));
  3310.  
  3311. Those two lines will not write the same values.  Trunc(), another
  3312. type transfer function, converts the real value 2.0 into the
  3313. integer value 2 before writing it.  The Integer "function" does
  3314. nothing at all, so the program just writes the real value as if it
  3315. were an integer, which is sure to produce some preposterous
  3316. number.
  3317.  
  3318. In general, casting an expression to a larger sized expression is
  3319. a bad idea, and casting a simple expression (an ordinal, real, or
  3320. pointer value) to a complex type (an array or record reference) or
  3321. vice versa will almost always produce nonsense results.
  3322.  
  3323.  
  3324.  
  3325. ===================================================================
  3326.  
  3327.                     Small Initialization Code
  3328.  
  3329. ===================================================================
  3330.  
  3331. You might, sometime, want to create a program that doesn't have
  3332. the overhead of normal PCQ Pascal programs.  For example, if you
  3333. never use Pascal files, there's no point having all the code for
  3334. Writeln() in your program.  If you want to cut the start-up and
  3335. shut-down code that PCQ adds to your program to a minimum, you can
  3336. use the "-s" option (for Small) on the command line.  For example,
  3337. to compile Tiny.p with the small startup code, you would use the
  3338. following line:
  3339.  
  3340.         Pascal Tiny.p Tiny.asm -s
  3341.  
  3342. The overhead you get rid of is not useless fat, however, and one
  3343. of the problems with not having it is that you can't use it.  Put
  3344. another way, if you use the "-s" option on the command line, you
  3345. will not be able to use any Pascal IO routines.  Specifically, the
  3346. procedures and functions that become off limits are:
  3347.  
  3348.     Write, WriteLn, Read, ReadLn, Get,
  3349.     Put, Open, ReOpen, Close, IOResult
  3350.  
  3351. The compiler will flag references to all these identifiers with
  3352. the exception of IOResult, but keep in mind that the compiler will
  3353. never see references in separately compiled files (external file)
  3354. or object code libraries.  The moral of this story is that you
  3355. should exercise extreme care when using this option, or you will
  3356. end up linking both startup routines and crashing the machine
  3357. anyway.
  3358.  
  3359. So what, exactly, is missing?  The normal startup code does the
  3360. following:
  3361.  
  3362.     1. Handles the CommandLine or Workbench message.
  3363.     2. Opens Intuition, DOS, and the MathFFP library.
  3364.     3. Sets up Input and Output, opening a window if
  3365.        necessary.
  3366.     4. Initializes the memory allocation list and the
  3367.        open file list so they can be freed at exit.
  3368.     5. Sets up an exit procedure that will free up the
  3369.        memory and files.
  3370.  
  3371. As you can see, there are several pretty big routines: Open(),
  3372. Close(), setting up Input and Output based on the way the program
  3373. was run and the contents of StdInName and StdOutName, the exit
  3374. procedure that frees everything, etc.  The small initialization
  3375. code does this:
  3376.  
  3377.     1. Handles the CommandLine or Workbench message.
  3378.     2. Opens Intuition, DOS and the MathFFP library.
  3379.     3. Intializes the memory list, and sets up a simple
  3380.        routine to free all the New() memory.
  3381.  
  3382. And that's it.  According to my preliminary results, this program:
  3383. "Program Test; begin end." compiles to about 2.5k normally, and
  3384. less than 700 bytes using the small initialization code.
  3385.  
  3386.  
  3387.  
  3388.  
  3389. ===================================================================
  3390.  
  3391.                        Execution Profiling
  3392.  
  3393. ===================================================================
  3394.  
  3395. I recently read the story of a guy who spent a couple of weeks
  3396. optimizing a particular routine, although he knew it was rarely
  3397. used.  Some time later, a bug report from the field told him that
  3398. the routine had never actually worked - but for years no one had
  3399. noticed because the routine had not been called, not even once.
  3400. The guy had completely wasted weeks of his time.
  3401.  
  3402. An execution profiler helps you avoid these sorts of mistakes by
  3403. showing you where the program spends most of its time.  It gives
  3404. you the time spent in the routine, the percentage of the total run
  3405. time it represents, and the number of times the routine was
  3406. called.
  3407.  
  3408. To use the execution profiler, just add the switch "-p" to your
  3409. command line when you compile the program.  If your program uses
  3410. external files (and you want them to be profiled), be sure to
  3411. compile them with the "-p" switch also.  As you run the program,
  3412. special code will keep track of the amount of time spent in each
  3413. routine, and at the end of the program a report will be written
  3414. out.  It is written using the normal Write() and Writeln() calls,
  3415. so your program must not do away with the standard output channel
  3416. (i.e.  you shouldn't use the small initialization code option, nor
  3417. should you define StdOutName as Nil).
  3418.  
  3419. Note that programs with the profiler information in them are
  3420. somewhat larger than normal, and run much slower because of all
  3421. the bookkeeping going on.  Since all the routines are slowed down
  3422. equally, their relative percentages of the total run time doesn't
  3423. change much, but you will definitely want to omit the profiler
  3424. code when you compile your final version.
  3425.  
  3426. How does the profiler work?  At the beginning of each routine, a
  3427. special procedure is called to mark the current time.  At the exit
  3428. of each routine, another special procedure is called to add the
  3429. elapsed time to the routine's total.  Note that time accrues to
  3430. only one routine, so the sum of the times for all the routines
  3431. should be about the same as the total run time.  At the end of
  3432. execution, a special exit procedure is called to display the
  3433. results.
  3434.  
  3435. The results you get from the execution profiler are rough
  3436. approximations.  To increase their accuracy, try to run the
  3437. program for as long as possible.  Since execution speed is slowed
  3438. down, this can be awfully dull.
  3439.  
  3440. If you are interested, the code for the profiler is included in
  3441. the runtime library as Utils/Profile.p.  If you don't like the
  3442. format of the report, or want to keep track of other information,
  3443. you might want to give it a look.
  3444.  
  3445.  
  3446.  
  3447.  
  3448. ===================================================================
  3449.  
  3450.                           External Files
  3451.  
  3452. ===================================================================
  3453.  
  3454. In developing the compiler I found that writing the entire thing
  3455. in one source file was just too much - the intermediate assembly
  3456. files were huge, and the compile times were ridiculous.  In order
  3457. to split things up a bit I added a method for separate
  3458. compilation, similar in purpose to Turbo Pascal's units, but less
  3459. powerful.
  3460.  
  3461. External files have the following format:
  3462.  
  3463.            <External File> ::= External; <Definitions>
  3464.  
  3465. In other words, an external file starts with the reserved word
  3466. External, a semicolon, then any number of definition blocks.
  3467. These definition blocks, as defined above, can be functions,
  3468. procedures, variables, etc.
  3469.  
  3470. Whenever you define a procedure or function, PCQ Pascal "exports"
  3471. the identifier so it can be used by other files.  These other
  3472. files refer to the routine by including an external reference in
  3473. their code (see External References in the Procedures and
  3474. Functions section).  Thus if you define the procedure DoIt in your
  3475. external file, you would include the following declaration in any
  3476. other file in which you used the routine:
  3477.  
  3478.                         Procedure DoIt;
  3479.                             External;
  3480.  
  3481. That declaration tells the compiler that it should "import" the
  3482. identifier from some other file.
  3483.  
  3484. Defining variables and typed constants at the global level in an
  3485. external file is a bit more complicated.  Suppose, for example,
  3486. that you have a global variable in your main program, but you also
  3487. want to refer to it in your external file.  If you declare it
  3488. normally in the external file, you might expect that PCQ would
  3489. reserve two memory areas for the one variable, one in the main
  3490. program and one in the external file.
  3491.  
  3492. Because of that problem, variables and typed constants at the
  3493. global level (only) are by default assumed to be defined only in
  3494. normal program files.  Thus if you define a global variable in an
  3495. external file, PCQ will assume that the variable should be
  3496. imported from some other file, and will not allocate space.  This
  3497. assumption can be overridden by the $S directive, however.
  3498.  
  3499. If you have used an external file, you need to be sure its
  3500. routines are included in the final executable program.  To do
  3501. that, you have to include the file name in the linker command, as
  3502. follows:
  3503.  
  3504.     Blink Main.o Extern1.o ... to MainProgram Library PCQ.lib
  3505.  
  3506. In other words you include any external object files (the output
  3507. of the assembler) in the linker command after the main file, but
  3508. before the "to" keyword.  They can be in any order.
  3509.  
  3510. Although Pascal is a case-insensitive language, assembly is not.
  3511. Thus when you make external references you must be sure that the
  3512. very first reference in your code - either the variable
  3513. declaration or the actual header for the procedure or function -
  3514. has the same case as the definition in the external file.
  3515. Subsequent uses can have any case - the first one is used to
  3516. generate the reference.
  3517.  
  3518.  
  3519.  
  3520.  
  3521. ===================================================================
  3522.  
  3523.                        Calling Conventions
  3524.  
  3525. ===================================================================
  3526.  
  3527.  
  3528. PCQ Pascal normally pushes function arguments on the stack in the
  3529. opposite order that a C compiler would.  That makes it difficult
  3530. to call C routines, since the order of the parameters must be
  3531. reversed.  PCQ, therefore, let's you specify that you would rather
  3532. use the C calling convention for a routine.
  3533.  
  3534. To do that, you use the compiler directive {$C+}.  If the C
  3535. calling convention is in effect when a routine is declared, that
  3536. routine's parameters will be pushed from right to left.  If you
  3537. use a routine from an external file that uses C calling
  3538. conventions, you must be sure that $C+ is in effect when the
  3539. External declaration is made in the main file.  Similarly, if $C+
  3540. is in effect when a forward declaration is made, that routine will
  3541. use C calling conventions regardless of the setting when the
  3542. routine is actually defined.
  3543.  
  3544. If you intend to use a variable number of parameters, the routine
  3545. must be declared under C calling conventions.  Unless you are
  3546. doing that or calling C routines, however, you should probably
  3547. steer clear of the $C+ directive.  At some later time you'll
  3548. probably leave it out of a declaration, which will cause a very
  3549. difficult to find bug.
  3550.  
  3551.  
  3552.  
  3553. ===================================================================
  3554.  
  3555.                  Notes to Assembly Programmers
  3556.  
  3557. ===================================================================
  3558.  
  3559. In previous versions of the compiler, the registers from d2 to d7,
  3560. a2 and a3 were all available at any time, and the scratch
  3561. registers were available between statements.  That is no longer
  3562. true, so some assembly routines might have to be rewritten.
  3563.  
  3564. Version 1.2 of PCQ now uses registers much more efficiently, which
  3565. means that all of the data registers can be put to use.  PCQ
  3566. allocates registers from d7 down to hold subexpression results, so
  3567. the availability of registers within expressions depends on the
  3568. Pascal code.  Between statements, all data registers are still
  3569. available.
  3570.  
  3571. Address registers are used as before: a7 is the stack pointer, a6
  3572. is used to point to the library base, a5 points to the stack
  3573. frame, and a4 is used to point to previous frames.  The compiler
  3574. can use a3 and a2 during expressions to hold intermediate address
  3575. values.
  3576.  
  3577. The system routines consider d0,d1,a0 and a1 as scratch, but
  3578. preserve all other registers.
  3579.  
  3580.  
  3581.  
  3582.  
  3583.  
  3584. ===================================================================
  3585.  
  3586.                               Errors
  3587.  
  3588. ===================================================================
  3589.  
  3590. When the compiler runs across some sort of error in your program,
  3591. it prints out the current and previous lines, with the general
  3592. area of the error highlighted.  On the next line, it tells you the
  3593. line number and current procedure or function being defined, plus
  3594. some (hopefully) descriptive text.
  3595.  
  3596. The first error is normally fairly accurate.  After that, however,
  3597. the compiler might start coming up with a lot of spurious
  3598. complaints that are best ignored.  For this reason, PCQ Pascal
  3599. automatically aborts after four errors.
  3600.  
  3601. If you specified the "-q" Quiet command line option, the error
  3602. reports will have a much more regular form, which is:
  3603.  
  3604. "source file name" At ##,## : Error Text
  3605.  
  3606. The quotes, colon, and the word "At" are all literal.  The first
  3607. ## is the line, and the second is the column.  This format is
  3608. designed to make automated compilation routines easier to develop.
  3609.  
  3610.  
  3611.  
  3612.  
  3613.  
  3614. ===================================================================
  3615.  
  3616.                              Sources
  3617.  
  3618. ===================================================================
  3619.  
  3620. I wrote PCQ Pascal as a learning experience, and it case you're
  3621. wondering I sure learned a lot.  Where did I go for information?
  3622. First, let's look at information specifically about the Amiga.
  3623.  
  3624. Amiga 1.3 Native Developer's Update.  This is a package of four
  3625. disks distributed by Commodore (CATS, specifically).  It has the
  3626. complete C and assembly language include libraries, Amiga.lib,
  3627. ALink, and all sorts of other things.  Perhaps more importantly,
  3628. it also has the Amiga Autodocs, a set of documentation files that
  3629. explain each and every function available in the standard Amiga
  3630. libraries and devices.  It explains each one individually,
  3631. however, so you still need a more general source.  For $20 U.S.,
  3632. however, these disks are a bargain.  The 2.0 update should be out
  3633. eventually, but as I write this it's still unavailable, so you
  3634. should send $20 and ask for the 1.3 update from:
  3635.  
  3636.         C.A.T.S
  3637.         1200 Wilson Drive
  3638.         West Chester, PA 19380
  3639.  
  3640.  
  3641. Amiga ROM Kernel Manuals.  This is the official set of books for
  3642. Amiga programming, and if you don't have them you are handicapped.
  3643. The last version I have is from AmigaOS version 1.1 so I'm not
  3644. sure how they are organized these days, but you should definitely
  3645. get the one that explains Intuition, and if you can still afford
  3646. it, the one that explains Libraries and Devices.  They are big and
  3647. very expensive, but it's hard to get by without them.  Some folks,
  3648. by the way, will also tell you that they are mistake-ridden and
  3649. difficult to understand, but I found them to be very accurate and
  3650. clear.  I think some programmers like to blame their lack of
  3651. understanding on others....
  3652.  
  3653. Anders Bjerin's C manual.  I've never looked at this, so I have no
  3654. idea of what it covers.  It appears to cover lots of Intuition and
  3655. Graphics topics, and the C slant shouldn't be too much of a
  3656. problem.  It's available on Fred Fish disks 456 & 457, and unpacks
  3657. to four full disks of documentation.
  3658.  
  3659.  
  3660. As far as information about compilers in particular, I referred to
  3661. the following sources:
  3662.  
  3663. PDC, a freely distributable C compiler supported by Jeff Lydiatt.
  3664. This is a very good program, although it has been eclipsed
  3665. recently by DICE, GCC, and other really good C compilers.  I
  3666. learned, and used, a lot about activation frames from PDC's
  3667. output, although PDC's source code remains a mystery.
  3668.  
  3669. Pascal-S source code.  This is a small demonstration of a Pascal
  3670. p-code compiler produced years ago at Wirth's place, ETH Zurich.
  3671. It can answer some questions, but isn't a really good example of
  3672. programming style.
  3673.  
  3674. Small-C source code.  Small-C is another freely distributable C
  3675. compiler, originally described in Dr. Dobb's Journal years ago.
  3676. It is not very powerful, but the simplicity of the source code
  3677. makes it a very practical reference.  It is one of the compilers
  3678. used to bootstrap PCQ.
  3679.  
  3680. Brinch Hansen on Pascal Compilers, by Per Brinch Hansen.  This
  3681. book was of some use, which is more than I can say about the other
  3682. half dozen I read while writing this.  From this book I mainly
  3683. learned about all the things I was doing wrong.  Great.
  3684.  
  3685. The Toy Compiler series in Amiga Transactor, written by Chris
  3686. Gray.  This series is very informative, and is written by the
  3687. author of Draco.  Gray also writes compilers for a living, so he
  3688. actually knows what he's talking about.  Unfortunately this series
  3689. is hard to find, because the Transactor is out of business.  Ask
  3690. around, though - it's worth it.
  3691.  
  3692. Compilers: Principles, Techniques and Tools, by Aho, Sethi and
  3693. Ullman.  This is the big book, the so-called Dragon book, the
  3694. first and last word on compiler writing.  If you want to know
  3695. about it, it's in there, but you had better have a pretty decent
  3696. math background.  Although it was a textbook for a class I took, I
  3697. have never read more than a few pages of it.
  3698.  
  3699.  
  3700.  
  3701. ===================================================================
  3702.  
  3703.                     Improvements On The Burner
  3704.  
  3705. ===================================================================
  3706.  
  3707. I've been using 1.2 for several months before I issued it, so I'm
  3708. relatively confident of its quality.  Nonetheless, it's such a
  3709. major change that I expect there will be problems.  Therefore my
  3710. first priority, as always, will be bug fixes.
  3711.  
  3712. Next comes optional C calling conventions, integrated peephole
  3713. optimizing, and possibly IEEE single precision reals.  That's all
  3714. easy enough.
  3715.  
  3716. Version 1.3 will be a compatibility release.  It will include
  3717. Turbo-style strings, function return values, double precision
  3718. reals, and Turbo types: Word, LongInt, ShortInt, etc.  Address
  3719. will become Pointer, Integer will become LongInt, Short will
  3720. become Integer, Exit will become Halt, etc.  I may even implement
  3721. Unit syntax.
  3722.  
  3723. The other area I'd like to explore is debuggers, preferably source
  3724. level.  I've been looking for the source code to one of those
  3725. monitor programs, but have yet to find it.
  3726.  
  3727.  
  3728.  
  3729. ===================================================================
  3730.  
  3731.                           Update History
  3732.  
  3733. ===================================================================
  3734.  
  3735. Version 1.2d (August 22, 1992)
  3736.  
  3737.   o   Fixed a problem with typed constant arrays - array elements
  3738.       with an odd size were not padded.
  3739.  
  3740. Version 1.2d (February 15, 1992)
  3741.  
  3742.   o   Fixed the date routines in DateTools
  3743.   o   Fixed a bug with range types that caused them to be one
  3744.       byte long.
  3745.   o   Comparisons of structured types didn't work - they do now.
  3746.   o   Fixed a problem with the iff.library's GetColorTable glue
  3747.       routine.
  3748.  
  3749. Version 1.2d (September 18, 1991)
  3750.  
  3751.   o   Fixed a bug in multi-dimensional array references.
  3752.   o   Fixed a mistake in the Exec/ExecBase.i file.
  3753.   o   Added support for variable numbers of arguments, including
  3754.       the va_start and va_arg routines.
  3755.   o   Added support for C style parameter passing, i.e. right-to-
  3756.       left.
  3757.   o   Added the $X directive for ignoring function return values.
  3758.  
  3759. Version 1.2c (August 10, 1991)
  3760.  
  3761.   o   The compiler would not allow New() and Dispose() in programs
  3762.       compiled under the small initialization code option.
  3763.   o   Since type casts were not functions, constant integers were
  3764.       never extended if they were cast to, say, a pointer type.
  3765.       That's not really a bug, but since it is difficult to get
  3766.       around, the compiler now promotes integer types when it
  3767.       should.
  3768.   o   The CHIP and FAST keywords were added.
  3769.   o   Added variant records.
  3770.   o   Added the exception that allows pointer declarations to refer
  3771.       to undefined types.
  3772.   o   Added support for the "e" scaling term in floating point
  3773.       constants, so for example "2e2" means 2 * 10^2.
  3774.   o   Added the $N directive.
  3775.   o   Added (* and *) as synonyms for { and }
  3776.   o   Added execution profiler.
  3777.   o   Some of the floating point output routines fixed in previous
  3778.       versions had not yet been incorporated into PCQ.lib.
  3779.   o   Modified the IF statement to omit code inside constant FALSE
  3780.       IF statements.
  3781.   o   Fixed a bug in the ReadInt routine when no digits were read.
  3782.  
  3783. Version 1.2b (June 22, 1991)
  3784.  
  3785.   o   The compiler would ignore function or procedure parameters
  3786.       following negative constants.
  3787.   o   The compiler now ensures that each element of an array is
  3788.       word-aligned, if the element is larger than one byte.
  3789.   o   Fixed the looping problem with REPEAT/UNTIL.
  3790.   o   The $A didn't work between the routine header and the code
  3791.       area.
  3792.  
  3793. Version 1.2a (June 8, 1991)
  3794.  
  3795.   o   The XOR operator would produce illegal assembly commands.
  3796.   o   Some floating point comparisons would produce incorrect
  3797.       results.
  3798.   o   The $A assembly directive now works anywhere in the code,
  3799.       not just in procedures and functions.
  3800.   o   The compiler used to accept unknown identifiers in typed
  3801.       constants (as operands of the @ operator).
  3802.   o   The INC and DEC statements were not handling Inc(var1,var2)
  3803.       forms correctly.
  3804.  
  3805. Version 1.2 (April 18, 1991)
  3806.  
  3807.   o   Fixed strlen and CreateTask() to work with 32-bit memory.
  3808.   o   Re-wrote the expression parsing and code generating routines
  3809.       completely.  The routines now use registers much more
  3810.       effectively, and provide a good base for the separate
  3811.       peephole optimizer.
  3812.   o   Added a few Turbo Pascal features:  you can now use typecasts
  3813.       anywhere, even in address calculations.  Thus you can now
  3814.       write something like RecordType(Pointer^).Field, which in
  3815.       version 1.1 was illegal.
  3816.   o   Changed the FOR statement significantly in order to make it
  3817.       more efficient, and more like Turbo.  It boils down to two
  3818.       differences:  FOR loops no longer run a minimum of once (e.g
  3819.       for i := 1 to 0 do ...  will execute zero times), and the BY
  3820.       clause is gone.
  3821.   o   Added short circuit evaluations, automatic floating point
  3822.       conversions, Heap functions, Reset and Rewrite.
  3823.   o   You can now use any standard functions or operators in
  3824.       constant expressions.
  3825.   o   Changed the Read routines to comply with Standard Pascal and
  3826.       Turbo, in that any white space is skipped before reading
  3827.       integers and reals.  It used to stop at EOLNs.
  3828.  
  3829.  
  3830. Version 1.1d, May 6, 1990:
  3831.  
  3832.     I've begun accumulating small changes under a new version
  3833. number purely for aesthetics.  The first difference is that the
  3834. compiler now creates a SECTION for data only if it has to.  That
  3835. sounds like an efficiency issue, but actually it wasn't creating a
  3836. SECTION at all if it was compiling an External unit.
  3837.     When StdOut is a file, the compiler no longer writes the line
  3838. numbers and all that stuff.  I have also made what I hope is the
  3839. last fix to the real number reading routines.
  3840.     The routine that compares include file names to the list of
  3841. previously included files is now case-insensitive.  I can't
  3842. imagine why it wasn't before.
  3843.  
  3844. Version 1.1c, April 6, 1990:
  3845.  
  3846.     I should have guessed that the problem recognizing the sign of
  3847. small real numbers on output would have a symmetric problem for
  3848. input.  It did, and now it doesn't.  I also fixed the problem with
  3849. signs on real constants.  I also added the exp() and ln()
  3850. functions recently sent to me by Martin Combs.  To avoid inflation
  3851. of version numbers, I've changed the date but kept the same
  3852. version.
  3853.     I've been thinking about adding peephole optimization to the
  3854. process, and rather than doing it the right way I've been playing
  3855. with a separate program.  To make that easier, I've removed short
  3856. branches from the code generated.  A68k adds them where necessary
  3857. anyway.
  3858.  
  3859. Version 1.1c, March 3, 1990:
  3860.  
  3861.     The only changes to the compiler are the new standard
  3862. functions.  The more significant changes were in the runtime
  3863. library.  First, I replaced the sin() and cos() functions based on
  3864. suggestions by Martin Combs - the result is that the results are
  3865. accurate to about 3 digits, and only slightly slower.  Martin was
  3866. kind enough to send along a very useful set of routines, which
  3867. also included the tan() and arctan() functions.  I also fixed the
  3868. routine that writes real numbers, so values between -1.0 and 0.0
  3869. now include the minus sign.
  3870.  
  3871. Version 1.1b, February 6, 1990:
  3872.  
  3873.     This program is over a year old.
  3874.     Added the Sqr() function.  Sqr(n) is the same as n * n, but
  3875. marginally faster and smaller.  Also, the compiler used to
  3876. generate lots of errors when an include file was missing.  Now it
  3877. skips the rest of the comment, like it should.
  3878.     Apparently floating point constants didn't used to work.  Why
  3879. am I always the last to know?  I also added the Sin() and Cos()
  3880. functions, based on an aside during a lecture on an entirely
  3881. different topic.
  3882.     Later I added the sqrt() function, using Newton's method.
  3883.  
  3884. Version 1.1a, January 20, 1990:
  3885.  
  3886.     Fixed a bug in the WriteArb routine that manifested itself
  3887. whenever you wrote to a 'File of Something'.
  3888.     Fixed a bug left in the floating point math library.  It seems
  3889. that it had not been updated for the all the 1.1 changes, so
  3890. during linking it required objects that aren't around anymore.
  3891. Since floating point math is now handled by the compiler, I hadn't
  3892. noticed it before.
  3893.  
  3894. Version 1.1, December 1, 1989:
  3895.  
  3896.     This version is completely re-written, and has far too many
  3897. changes to list them individually here.  The main changes are the
  3898. with statement, the new IO system, a completely redesigned symbol
  3899. table, nested procedures, and several new arithmetic operators.
  3900. In order to help port programs from Turbo Pascal and C, I added
  3901. typed constants, the Goto statement, and the normal syntax for
  3902. multi- dimensional arrays.
  3903.  
  3904. Version 1.0c, May 21, 1989:
  3905.  
  3906.     I changed the input routines around a bit, using DOS files
  3907. rather than PCQ files.  I buffered the input, and made the
  3908. structure more flexible so I could nest includes.  Rather than
  3909. make up some IfNDef directive, I decided to keep track of the file
  3910. names included and skip the ones already done.  Buffering the
  3911. input cut compile times in half.  I would not have guessed
  3912. buffering would be that significant, and I suppose I should
  3913. rethink PCQ input/output in light of this.
  3914.     I added code to check for the CTRL-C, so you can break out
  3915. early but cleanly.  The Ports.i include file had a couple of
  3916. errors, which I fixed, and I also fixed the routine that opens a
  3917. console for programs that need one.  It used to have problems when
  3918. there were several arguments in the first write().
  3919.     I added the SizeOf() function, floating point math, and the
  3920. standard functions related to floating point math.
  3921.     There were several minor problems in the include files which I
  3922. found when I got the 1.3 includes, the first official set I've had
  3923. since 1.0.
  3924.     I relaxed the AND, OR and NOT syntax to allow any ordinal
  3925. type.  This allows you to get bitwise operations on integers and
  3926. whatever.  I also added a standard function called Bit(),
  3927. described above.  These are all temporary until I can get sets
  3928. into the language.
  3929.     I finally added string indexing.  In doing so I found a bug in
  3930. the addressing routine selector(), so I rewrote it to be more
  3931. sensible.  I think it also produces larger code, but I'm not too
  3932. worried because I'm going to add expression trees soon anyway.
  3933.  
  3934. Version 1.0b, April 17, 1989:
  3935.  
  3936.     I fixed a bug in the way complex structures were compared.  It
  3937. seems that one too many bytes were considered, so quite often the
  3938. comparison would fail.
  3939.  
  3940. Version 1.0a, April 8, 1989:
  3941.  
  3942.     This version added 32 bit math, and fixed the case statement.
  3943. The math part was just a matter of getting the proper assembly
  3944. source, but I changed the case statement completely.  Version 1.0
  3945. of the compiler produced a table that was searched sequentially
  3946. for the appropriate value, which if found was matched up with an
  3947. address.  I thought all compilers did this, but when debugging a
  3948. Turbo Pascal program at work I found that it just did a bunch of
  3949. comparisons before each statement, as if it were doing a series of
  3950. optimized if statements.  I had thought of this and rejected it as
  3951. being too simplistic, but if it's good enough for Turbo it's good
  3952. enough for me.
  3953.     The next thing I changed in this release was the startup code.
  3954. You can now run PCQ Pascal programs from the Workbench.  This was
  3955. just a matter of taking care of the Workbench message, but I also
  3956. fooled around with standard input and output.  If you try to read
  3957. or write to standard in or out from a program launched from the
  3958. Workbench, the run time code will open a window for you.
  3959.     I also fixed one bug that I found:  an array index that was
  3960. not a numeric type had its type confused.  Nevermore.
  3961.  
  3962. Version 1.0, February 1, 1989
  3963.  
  3964.     Original release.
  3965.  
  3966.  
  3967.  
  3968. ===================================================================
  3969.  
  3970.                Other Notes, Copyright & My Address
  3971.  
  3972. ===================================================================
  3973.  
  3974. This documentation, the source code for the compiler, the compiler
  3975. itself, the source code for the run time library, and the run time
  3976. library itself, are all (ahem):
  3977.  
  3978.                 Copyright (c) 1989 Patrick Quaid.
  3979.  
  3980. This registered version of the compiler is not distributable, but
  3981. there is a copy of the unregistered compiler included in the
  3982. distribution as PCQ12b.LZH.  If you want to pass that one around,
  3983. you can, but you should only include that file, the assembler, and
  3984. the linker.
  3985.  
  3986. Registered users can receive the latest version of the compiler
  3987. for the cost of a disk and return postage.  If there are
  3988. substantial improvements or serious bug fixes, I'll send you a
  3989. postcard letting you know that an update is available.
  3990.  
  3991. A printed, bound version of this documentation (combined with
  3992. PCQ.lib.DOC) is available from me for $15, which is about what it
  3993. costs to print and ship.  It isn't just a printer dump, however -
  3994. it's entirely reformatted and laser printed.
  3995.  
  3996. Any questions, comments, or whatever can be addressed to:
  3997.  
  3998.       Pat Quaid
  3999.       2250 Clarendon Blvd, Apt #1209
  4000.       Arlington, VA 22201
  4001.       USA
  4002.  
  4003.       Telephone: (703) 524-8945
  4004.  
  4005. Please note that my address and phone number have changed since
  4006. April '92.
  4007.  
  4008. You are much more likely to be able to contact me by mail than by
  4009. phone, but I certainly don't mind if you try.  Enjoy the compiler.
  4010.